strtotime result makes no sense, php bug?

2019-04-03 13:44发布

问题:

The following line:

echo date('d', strtotime('First Saturday August 2015'));

prints 08, which doesn't seem to make any sense because the first occurrence of a day of the week can't be after the 7th.

Is it a php bug or a php bug or maybe even a php bug? I don't know...

php version: 5.5.19

回答1:

Update #1: explained below the big difference that a simple word like "of" makes, after I investigated a little in the PHP source code.

Update #2: There actually is a documentation page on PHP manual that explains the formats of dates accepted by strftime(). I just was not aware of it until now. Thanks @Outspaced for providing the link in their answer.

For a quick and easy reading skip the section Update #1.


The initial answer:

Indeed,

echo date('Y-m-d', strtotime('First Saturday August 2015'));

prints:

2015-08-08

But

echo date('Y-m-d', strtotime('First Saturday of August 2015'));

prints the correct date:

2015-08-01

Since strtotime() tries to "understand" English, I guess you and it speak different dialects :-)

Update #1:

After some reading in the PHP source code of function strtotime(), I think that it parses First Saturday August 2015 as First Saturday followed by August 2015.

August 2015 is an absolute expression and because there is no indication about the day it produces 2015-08-01 (the 1st of August 2015) which is a reasonable guess (the only one possible, I think).

First Saturday is a relative expression. It is relative to an absolute mark provided in the string (August 2015) or as a second parameter of strtotime() and it "shifts" the timestamp of the absolute mark back or forward with some amount.

Putting them together, strtotime() interprets First Saturday August 2015 as First Saturday counting since August 1, 2015 and that is, indeed, August 8, 2015.

On the other hand, First Saturday of August 2015 is parsed using a different rule. One of next, last, previous, this or any ordinal number from first to twelfth, followed by a weekday name (full or abbreviated) and followed by of is parsed as a weekday of the provided month (or the current month if none is provided in the string).

Update #2

After I found out that the format of the string accepted by strtotime() is actually explained in the PHP documentation, the explanation became more simple. Take a look at the second "Note:" box in the documentation page.

First Saturday August 2015 is explained at item #4 in the note:

"ordinal dayname" does advance to another day.

First Saturday of August 2015 is explained at item #6 of the note:

"ordinal dayname 'of'" does not advance to another day.

The note ends with an entire block of explanation dedicated to the magical word "of".



回答2:

You need an 'of':

date('d/m/Y', strtotime('First Saturday of August 2015'))

see the manual: http://docs.php.net/manual/en/datetime.formats.relative.php



回答3:

As stated, PHP didn't quite understand your choice of dialect. If you plan on accepting varied input from your users (not a bad idea) to express a date, I suggest doing some normalization of that user input yourself so that you can submit a predictable format to strtotime.