php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #60353 Date-related "Relative Formats" doesn't indicate month behaviour
Submitted: 2011-11-21 22:05 UTC Modified: 2011-11-27 03:59 UTC
From: frozenfire@php.net Assigned: frozenfire (profile)
Status: Closed Package: Documentation problem
PHP Version: Irrelevant OS:
Private report: No CVE-ID: None
 [2011-11-21 22:05 UTC] frozenfire@php.net
Description:
------------
A fellow on reddit.com/r/PHP mentioned that the documentation for Relative 
Formats for dates is missing information on how relative months work.

Here's the relevant comment: 
http://www.reddit.com/r/PHP/comments/mk3ub/strtotime_wtf/c31lhav

"echo date("Y-m-d", strtotime("+1 month 2011-11-30"));
returns: 2011-12-30 // wtf? but I wanted 2011-12-31

This is why you don't use months when calculating dates. A month is ambiguous. 
Think about it - since months vary, which month is it supposed to use to 
calculate 1 month? November or December?

Since The starting date is in November, it assumes that is the first month it 
should start calculating from. So, for the first iteration, 1 month is 30 days. 
However, it recalculates what a month is for every iteration.

consider this:
echo date("Y-m-d", strtotime("+1 month 2011-11-30"));
// 2011-12-30 or 30 days
echo date("Y-m-d", strtotime("+2 month 2011-11-30"));
// 2012-01-30 or 61 days
echo date("Y-m-d", strtotime("+30 days 2011-11-30"));
// 2011-12-30
echo date("Y-m-d", strtotime("+60 days 2011-11-30"));
// 2012-01-29

Notice how when I use +2 months it suddenly becomes 61 days. This is because it 
starts in December on the second iteration, and it recalculates what a month is 
based on that."

This behaviour should be documented in the datetime.formats.relative document.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-11-27 03:58 UTC] frozenfire@php.net
Automatic comment from SVN on behalf of frozenfire
Revision: http://svn.php.net/viewvc/?view=revision&revision=320010
Log: Added note regarding the behaviour of relative months. Closes bug #60353.
 [2011-11-27 03:59 UTC] frozenfire@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: frozenfire
 [2011-11-27 03:59 UTC] frozenfire@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.


 [2015-02-03 18:28 UTC] teo8976 at gmail dot com
@frozenfire Hey man you forgot NEGATIVE values.

The current explanation clearly doesn't explain how negative month values are handled.

31 december -1 months -> 1 december
31 december -2 months -> 31 october
31 december -3 months -> 1 october
31 december -4 months -> 31 august

Documentation definitely needs to explain what the hell the logic behind that is, because it doesn't make any sense.
 [2015-02-03 20:33 UTC] teo8976 at gmail dot com
Actually, the current description for month relative value behavior is fundamentally flawed, even for positive values.

"Relative month values are calculated based on the length of months that they pass through"
That's intrinsically ambiguous. That doesn't even mean anything. WHAT months that they pass through?

1) Jan 31 + 1 months yields March 3. 
2) Jan 31 + 2 months yelds March 31.

There's no interpretation of the documented definition that can explain both.

"Based on the length of months that they pass through".
1) By adding 1 month to January 31, we'll "pass through" the month of January. January has 31 days, hence we will add 31 days. That actually yields March 3, but then we have passed through 2 months, which contraddicts the premise. But let's assume that's ok.
2) Then, adding 2 months to January 31 means passing through 2 months: January and February, which have 31 and 28 days respectively (or 29 depending on the year). Hence one would expect to obtain March 28 (or 29), instead it yields March 31: in no way is the number of days based on the length of the months that are "passed through".


The REALITY of what happens is: the number of months is added (algebrically, i.e. added or subtracted depending on sign) to the index of the month. Then the resulting date is WRAPPED, i.e. February 31 becomes March 3, or April 31 becomes May 1, etc (regardless of the sign of the relative value).

The documentation should be unambiguous and reflect the real behavior. The current one does neither.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Tue Oct 27 07:01:23 2020 UTC