When adding a month to with DateTime::modify method, the result skips February.
Why isn't it outputing 2020-02-31?
How to output 2020-02-29 using DateTime? (Last day of the month).
$date = new DateTime("2020-01-31");
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-03-02
PHP DateTime::modify("+n month") adds between 28 to 31 days to the current day, depending of the month and year.
Solution
I suggest you increment months from the first day of the month by using the modify and format methods:
// Instanciates the DateTime object.
$date = new DateTime("2020-01-01");
// Adds a month to the date.
$date->modify("+1 month"); // 2020-02-01
// Format the date with "t" (gets the last day of the month).
$date->format("Y-m-t"); // 2020-02-29
Incrementing from the first day of the month will never raise the February problem which is quite a quite common, thinking that PHP DateTime will smartly add a month from 2020-02-29 and output 2020-03-31.
Why it happens?
In the Gregorian calendar, the average length of a month is 30.436875 days:
30 days in April, June, September and November;
31 days in January, March, May, July, August, October and December;
28 days or 29 days (in leap years) in February.
PHP will add to the current date the exact number of days there is in the given month.
Thus, PHP will adjust the date after the first increntation if you are incrementing from the
last day of the month.
E.g.:
Let's add a month from the final day of March (31th).
Since the current month (March) has 31 days in it, PHP will increment 31 days to the date. Adding 31 days from 2020-03-31 will result in skipping the whole month of April.
$date = new DateTime("2020-03-31"); // 2020-03-31
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-05-01 | Added 31 days (since March has 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-06-01 | Added 31 days (since the new date is May 1st, which is a month with 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-07-01 | Added 30 days
Now, let's add a month to the final day of April (30th).
We can see that since the next months all have 30+ days in it, final day will stay the same,
until February of the next year. Since February always has between 28 and 29 days, adding 31 days to it will pass the month, and resulting date will be March 2nd.
$date = new DateTime("2020-04-30");
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-05-30 | Added 30 days.
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-06-30 | Added 31 days.
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-07-30 | Added 30 days.
// ...
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-01-30 | Added 31 days
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-03-02 | Added 31 days (since January has 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-04-02 | Added 31 days (since the new date is March 2nd, which is a month with 31 days).
This is why it is recommended to increment months from the first day of the month,
since the 1st is common to all months.
$date = new DateTime("2020-01-01"); // 2020-01-01
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-02-01 | Added 31 days
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-03-01 | Added 29 days (since 2020 is leap year, yee haw).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-04-01 | Added 31 days
I'm making an assumption that you are programming in php. If so, the documentation indicates that you will receive the results you are getting php DateTime::modify().
The documentation specifically indicates to "Beware"
Example #2 Beware when adding or subtracting months
<?php
$date = new DateTime('2000-12-31');
$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";
$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";
?>
The above example will output:
2001-01-31
2001-03-03
If you just need to move to the end of the next +1 month, what we often do in R is go to the end of the current month and then add +1 day and then go to the end of the month again. If you know that you are always at the end of the month, then just add +1 day and then go to the end of the month.
Other posts have some additional suggestions in this space
How to find the last day of the month from date?
Example from this post:
$date = new DateTime('now');
$date->modify('last day of this month');
echo $date->format('Y-m-d');
Related
I want to get the previous months date range with PHP. I have tried below function to get last month's date range.
$last_month_start_date = date('Y-m-d',strtotime('first day of last month'));
$last_month_end_date = date('Y-m-d',strtotime('last day of last month'));
echo $last_month_start_date.' - '.$last_month_end_date;
Output: 2019-09-01 - 2019-09-30
but how can I get previous month's date range with PHP?
can anybody help me with this?
To get Last to Last Month: If current month is October then below output gives first and last date of August
$last_to_last_start_date = $last_month_start_date = date('Y-m-d',strtotime('first day of last month -1 month'));
// outout 2019-08-01
$last_to_last_end_date = $last_month_end_date = date('Y-m-d',strtotime('last day of last month -1 month'));
// outout 2019-08-31
echo $last_to_last_start_date .' - '.$last_to_last_end_date ;
//Output : 2019-08-01 - 2019-08-31
Create a date-time object that is two months behind, then use a modifier of first/last day of this month. The this month modifier works on the month of the object, so if the object's date is in August, it will look for the first and last days of August.
This means that you can provide any value for -2 months (like February, -1 month) and it will get the start and end-dates for that month.
$start = new DateTime("-2 months");
$end = clone $start;
$start->modify("first day of this month");
$end->modify("last day of this month");
echo $start->format("Y-m-d")." - ".$end->format("Y-m-d");
In October 2019, this outputs,
2019-08-01 - 2019-08-31
Live demo at https://3v4l.org/udGtE
Wanted to get maximum weeks in a year, and thought this would be the simplest way to get this number, but I was surprised,that the last day in a year could be in the first week. Is this because these days are in the first half of the week?
So I know how to get the correct number, I'm just wondering about the logic.
<?php
echo (new DateTime('2016-12-31 00:00:00'))->format('W'); //52
echo (new DateTime('2017-12-31 00:00:00'))->format('W'); //52
echo (new DateTime('2018-12-31 00:00:00'))->format('W'); //01
echo (new DateTime('2018-12-30 00:00:00'))->format('W'); //52
echo (new DateTime('2019-12-31 00:00:00'))->format('W'); //01
echo (new DateTime('2019-12-30 00:00:00'))->format('W'); //01
echo (new DateTime('2019-12-29 00:00:00'))->format('W'); //52
echo (new DateTime('2020-12-31 00:00:00'))->format('W'); //53
Found by answered links (Wikipedia):
Last week
The last week of the ISO week-numbering year, i.e. the 52nd or 53rd
one, is the week before week 01. This week’s properties are:
It has the year's last Thursday in it.
It is the last week with a majority (4 or more) of its days in
December.
Its middle day, Thursday, falls in the ending year.
Its last day is the Sunday nearest to 31 December.
It has 28 December in it. Hence the latest possible dates are 28
December through 3 January, the earliest 21 through 28 December.
If 31 December is on a Monday, Tuesday or Wednesday, it is in week 01
of the next year. If it is on a Thursday, it is in week 53 of the year
just ending; if on a Friday it is in week 52 (or 53 if the year just
ending is a leap year); if on a Saturday or Sunday, it is in week 52
of the year just ending
It's probably following the ISO week date system. Citing that wikipedia article:
The ISO 8601 definition for week 01 is the week with the year's first Thursday in it.
If you want to get the last week of the year you can use this simple function:
function getIsoWeeksInYear($year) {
$date = new DateTime;
$date->setISODate($year, 53);
return ($date->format("W") === "53" ? 53 : 52);
}
I have problem with my code that gets the last day of the next 6 months. My code gets first the last day of the current month then using the date function + 6 months.
$lastday = date("Y-m-t");
$lastdayaftersixmonth = strtotime("$lastday +6 months");
But my problem is when it comes to months that do not have same number of days specifically in case of august and february. If the last day for august is 31, supposedly it must return february 28 (or 29 for leap year), but it returns March 2.
$date = date('Y-m-t',strtotime('+6 month'));
echo $date;
I need to fetch previous month from the current month passed. Tried below code and it does work for the month having 30 days but does not work for specific months having 31 days viz. March, May, July, October and December
Note: The question may sound repeated, but please read it completely till the end. You can check the same issue by changing the system and testing below code against it. I need the previous month output in format Jul
For Date: 30-Jul output is
Previous Month-Jun
Current Month-Jul
For Date: 31-Jul output is
Previous Month-Jul
Current Month-Jul
$prev_month = date('M', strtotime("last month"));
echo 'Previous Month--'.$prev_month;
echo 'Current Month--'.date('M');
Also tried echo date('M', strtotime("-1 Months")); but it outputs the same as above.
If current month is (August) with 31 days and so previous month is (July) with 31 days then it works and shows correct Previous Month i.e. July, but it does not work if current month has 31 days and previous month has 30 or lesser days.
How should I go about it to fetch correct previous month on the basis of current month ?
You simply try as
echo "Previous Month".date('M',strtotime('first day of last month'));
and for specific date you can simply use
echo date('M',strtotime('first day of last month',strtotime('30-Jun')));//May
You should pass in the date from the start of the month.
$startDate = date('Y-m-1');
$prevMonth = date('M', strtotime("last month", strtotime($startDate)));
see
PHP date() and strtotime() return wrong months on 31st
I want same day of month for each of the months that fall between start date and end date. Its just that if the month of the day is not valid for a particular month, you want last day of that month. is there any script?. What is have done is.
$startdate='2010-01-30';
$enddate='2011-01-30';
while ($startdate <= $enddate)
{
echo date('Y-m-d', $startdate ) . "\n";
$startdate = strtotime('+1 month', $startdate);/// for case of feb 28 days last date it should disply as it skips it
}
Expected out put:
For input $startdate='2012-01-30'; $enddate='2013-12-30' Result should be like this ==>
_2012-12-30_
2013-01-30
**2013-02-28**
2013-03-30
2013-04-30
2013-05-30
2013-06-30
2013-07-30
2013-08-30
2013-09-30
2013-10-30
2013-11-30
_2013-12-30_
Loop using for and adding $i months to the start date instead of constantly adding one month to the running value. This way it won't jump to 28th (or 29th) day because of february starting from march.