为什么 PHP date('m', strtotime('-1 months')) 今天不能正常工作? 07/31
Why does PHP date('m', strtotime('-1 months')) not work correctly for today? 07/31
我有一个脚本可以在 PHP 中获取当前和上个月,如下所示:
$currentMonth = date('m');
//Expected:07
//Result:07
$lastMonth = date('m', strtotime('-1 months'));
//Expected:06
//Result:07
今天刚好是31号,也就是7月底。这个结果是 PHP 的预期结果吗?
当使用 -31 天时,结果符合预期:
$lastMonth = date('m', strtotime('-31 days'));
//Expected:06
//Result:06
月份有"s"超额。应该是这样的:
$lastMonth = date('m', strtotime('-1 month'));
你可以这样做
$d = new DateTime();
$currentMonth = $d->format('m');
//Expected:07
//Result:07
print $currentMonth;
$d->modify('first day of previous month');
print "<br/>";
$lastMonth = $d->format('m');
//Expected:06
//Result:06
print $lastMonth;
这是 PHP 的日期字符串解析器的问题。看这里:
http://derickrethans.nl/obtaining-the-next-month-in-php.html
@先生Llama 制作了一个脚本来显示此问题影响的其他日期:http://codepad.viper-7.com/E4gP0W
我采用的解决方案:
//Date:07/31/15
$currentMonth = date('m');
//Result:07
$lastMonth = date('m', strtotime('first day of -1 months'));
//Result:06
这是一个不会过期的cleaner test case:
<?php
$origin = mktime(18, 0, 0, 7, 31, 2015);
var_dump( date('r', $origin), date('r', strtotime('-1 months', $origin)) );
string(31) "Fri, 31 Jul 2015 18:00:00 +0200"
string(31) "Wed, 01 Jul 2015 18:00:00 +0200"
我很确定这是一个文档问题,因为手册清楚地说明了这一点(强调我的):
Relative month values are calculated based on the length of months
that they pass through. An example would be "+2 month 2011-11-30",
which would produce "2012-01-30". This is due to November being 30
days in length, and December being 31 days in length, producing a
total of 61 days.
...这是错误的。
PHP 错误跟踪器有 tons of dupes about this. They're all closed as not a bug. Here's a relevant comment from 2009 解释:
I agree that this is an annoying behaviour.
Also, the implementation is problematic. Basically if you use '+1
month' it takes the month number, adds 1 and parses result as a new
date.
If you use '+1 month' on the first of the month, it sets the date to
the next first of the month.
This behaviour gives the impression, that php considers the length of
a month, which is not true.
But if you use '+1 month' on the last day of a month, the result is
unexpected as 2009-05-31 becomes 2009-06-31 which is an invalid date
and then interpreted as 2009-07-01.
This should at least be mentioned in the documentation.
-1 month
被解释为 "same day of month, last month"。如果这一天不存在,则日期会溢出到下个月。实际上结果与 strtotime("31.6.2015")
相同 - 试试吧!
我有一个脚本可以在 PHP 中获取当前和上个月,如下所示:
$currentMonth = date('m');
//Expected:07
//Result:07
$lastMonth = date('m', strtotime('-1 months'));
//Expected:06
//Result:07
今天刚好是31号,也就是7月底。这个结果是 PHP 的预期结果吗?
当使用 -31 天时,结果符合预期:
$lastMonth = date('m', strtotime('-31 days'));
//Expected:06
//Result:06
月份有"s"超额。应该是这样的:
$lastMonth = date('m', strtotime('-1 month'));
你可以这样做
$d = new DateTime();
$currentMonth = $d->format('m');
//Expected:07
//Result:07
print $currentMonth;
$d->modify('first day of previous month');
print "<br/>";
$lastMonth = $d->format('m');
//Expected:06
//Result:06
print $lastMonth;
这是 PHP 的日期字符串解析器的问题。看这里: http://derickrethans.nl/obtaining-the-next-month-in-php.html
@先生Llama 制作了一个脚本来显示此问题影响的其他日期:http://codepad.viper-7.com/E4gP0W
我采用的解决方案:
//Date:07/31/15
$currentMonth = date('m');
//Result:07
$lastMonth = date('m', strtotime('first day of -1 months'));
//Result:06
这是一个不会过期的cleaner test case:
<?php
$origin = mktime(18, 0, 0, 7, 31, 2015);
var_dump( date('r', $origin), date('r', strtotime('-1 months', $origin)) );
string(31) "Fri, 31 Jul 2015 18:00:00 +0200"
string(31) "Wed, 01 Jul 2015 18:00:00 +0200"
我很确定这是一个文档问题,因为手册清楚地说明了这一点(强调我的):
Relative month values are calculated based on the length of months that they pass through. An example would be "+2 month 2011-11-30", which would produce "2012-01-30". This is due to November being 30 days in length, and December being 31 days in length, producing a total of 61 days.
...这是错误的。
PHP 错误跟踪器有 tons of dupes about this. They're all closed as not a bug. Here's a relevant comment from 2009 解释:
I agree that this is an annoying behaviour.
Also, the implementation is problematic. Basically if you use '+1 month' it takes the month number, adds 1 and parses result as a new date.
If you use '+1 month' on the first of the month, it sets the date to the next first of the month.
This behaviour gives the impression, that php considers the length of a month, which is not true.
But if you use '+1 month' on the last day of a month, the result is unexpected as 2009-05-31 becomes 2009-06-31 which is an invalid date and then interpreted as 2009-07-01.
This should at least be mentioned in the documentation.
-1 month
被解释为 "same day of month, last month"。如果这一天不存在,则日期会溢出到下个月。实际上结果与 strtotime("31.6.2015")
相同 - 试试吧!