Using “+/-1 Month” with strtotime() function in PHP
PHP’s date function strtotime is used to parse about any English textual date-time into a Unix time-stamp.
Syntax: int strtotime ( string $time [, int $now = time() ] );
Examples:
<?php echo strtotime("now"); echo strtotime("+1 month"); ?>
PHP Docs : http://php.net/manual/en/function.strtotime.php
We’ve been using it in one of our projects, to get the 28th day of the last month.
What we were expecting:
Assume that today’s date is: 2014-12-31 and we wanted last month’s 28th.
Our code –
<?php $date = date('Y-m-28',  strtotime(“-1 month")) ?>
What do you think the $date will have? 2014-11-28 right? Wrong! It has 2014-12-28
Let’s look at another example –
Assume that today’s date is 2015-01-31, and we want to get the next month’s 28th.
Our code –
[code language="php"]&lt;?php $date = &lt;strong&gt;date('Y-m-28', strtotime(+1 month"))?&gt; [/code]
The $date will have 2015-03-28, instead of 2015-02-28 as expected.
Scratching your head? We were too, but delving a little deeper into the implementation made things clearer.
What’s happening?
If a month has 31 days and you are on the last day of that month, the strtotime(1 month”) returns the 1st day of that month.
If you are on last day of January, the strtotime(+1 month”) returns 3rd of March(not a leap year) / 2nd March(leap year).
Why it’s not a bug:
The current behavior is correct (in it’s own way). Let’s understand the process with an example:
- Assume today’s date is 2015-01-31, and you want to add”+1 month” to it.
- Actually +1 month increases the month number (originally 1) by one. This makes the date 2015-02-31.
- But the 2nd month (February) only has 28 days in 2015, so PHP auto-corrects this by just continuing to count days from February 1st. You then end up at March 3rd.You can see this here: http://ideone.com/HNalGr
- A similar thing happens, when you run”-1 month”.Γö¼├íYou can see this here: http://Ideone.Com/Yvm5p1
How to get what you want:
If you are using PHP 5.3 and above, to obtain the desired behavior, you can use the relative time stanza – first day of. This stanza can be used in combination with next month, fifth month or +9 months to go to the first day of the specified month. Instead of +1 month from what you’re doing, you can use this code to get the first day of next month like this:
<?php $d = new DateTime('2015-01-31'); $d->modify('first day of next month'); echo $d->format('Y-m-28'); ?>
How it works(the above solution):
- The new DateTime creates a date object of the date that we given as parameter or today date.
- Now, we are modifying the date to”first day of next month” (or”first day of last month”).
- Then we are echoing the date in the format that we want (i.e., yyyy-mm-28) by using format functionality of date
You can see this example(with execution) here:
A universal solution to get what you want:
If you are using PHP 5.3 or above, we recommend going with the above solution. Otherwise, you can use PHP’s mktime function to get what you need.
PHP Docs : http://php.net/manual/en/function.mktime.php
<?php $months = n; // Here n = ..-2,-1,0,1,2, ..(months to add or subtract) $years = n; // Here n = ..-2,-1,0,1,2,..(years to add or subtract) echo date('Y-m-28', mktime(0, 0, 0, date('m')+$months, 1, date('Y') + $years)); ?>
You can see this example(with execution) here:
The following are some more examples to understand better that how to use strtotime.
PHP fiddle link: http://ideone.com/VRMCyW
echo Date("Y-m-d", strtotime("2013-01-01 +1 Month -1 Day"));// 2013-01-31 echo Date("Y-m-d", strtotime("2013-01-31 +1 Month -3 Day"));// 2013-02-28 echo Date("Y-m-d", strtotime("2013-01-31 +2 Month"));// 2013-03-31 echo Date("Y-m-d", strtotime("2013-01-31 +3 Month -1 Day"));// 2013-04-30 echo Date("Y-m-d", strtotime("2013-12-31 -1 Month -1 Day"));// 2013-11-30 echo Date("Y-m-d", strtotime("2013-12-31 -2 Month"));// 2013-10-31 echo Date("Y-m-d", strtotime("2013-12-31 -3 Month"));// 2013-10-01 echo Date("Y-m-d", strtotime("2013-12-31 -3 Month -1 Day"));// 2013-09-30
Comments (3)