php – 为什么此日期功能仅在2016年12月30日之前有效?

我有这个代码

for ($i=1; $i<=12; $i++) {

    $monthNum  = $i;
    $monthName = date('F', mktime(0, 0, 0, $monthNum, 10));

    $date_established = strtotime($monthName);
    $date_established = strtotime('first day of this month', $date_established);
    $date_established = date('Y-m-d', $date_established);
    $date_established_end = date("Y-m-t", strtotime($date_established));

    echo $i .'::'. $monthName . '::' . $date_established . '::' . $date_established_end . '<br>';

}

到目前为止,它产生:

1::January::2016-01-01::2016-01-31
2::February::2016-02-01::2016-02-28
3::march::2016-03-01::2016-03-31
4::April::2016-04-01::2016-04-30
5::May::2016-05-01::2016-05-31
6::June::2016-06-01::2016-06-30
7::July::2016-07-01::2016-07-31
8::August::2016-08-01::2016-08-31
9::September::2016-09-01::2016-09-30
10::October::2016-10-01::2016-10-31
11::November::2016-11-01::2016-11-30
12::December::2016-12-01::2016-12-31

但是今天(2016年12月31日),所有这些都搞砸了:

1::January::2016-01-01::2016-01-31
2::February::2016-03-01::2016-03-31 
3::march::2016-03-01::2016-03-31 << duplicate
4::April::2016-05-01::2016-05-31
5::May::2016-05-01::2016-05-31 << duplicate
6::June::2016-07-01::2016-07-31
7::July::2016-07-01::2016-07-31 << duplicate
8::August::2016-08-01::2016-08-31
9::September::2016-10-01::2016-10-31
10::October::2016-10-01::2016-10-31 << duplicate
11::November::2016-12-01::2016-12-31
12::December::2016-12-01::2016-12-31 << duplicate

2016年12月31日有什么问题?为什么我的代码搞砸了?谢谢.

解决方法:

您的代码失败了:

$february = strtotime('February');
echo date(DATE_ISO8601, $february);

今天,2016年12月30日输出

2016-03-01T00:00:00+0000

嗯……为什么PHP说“二月”是“2016-03-01”?好吧,它与PHP如何填补缺失信息的空白有关:在没有明确给定绝对时间值的情况下,PHP使用当前日期和时间的值.

因此,由于它是12月30日东部时间13:29,以下是语义等价的:

strtotime('February');                       // you asked for
strtotime('February 30, 2016 13:29:47 EST'); // PHP interprets as
//                  ^^^^^^^^^^^^^^^^^^^^^ filled in from current time

显然,后者,解释日期是假的. PHP(通过底层库,实际上)使用2月30日= 2月29日1天= 3月1日的逻辑来改变解释日期.(更糟糕的是,在像2017年的非闰年,PHP将计算2月30日= 2月28日2天= 3月2日,输出为“2017-03-02T00:00:00 0000”!)

因此,在您要求PHP进行日期转换时,在这些情况下,您需要做的是明确的.这意味着而不是要求strtotime(‘二月’);你要求:

$year = date('Y');
$date_established = strtotime("$monthName 1, $year");

(或等效.重点是:不要让PHP用当前日期的值填充缺少的信息.)

另外:这些错误特别难以追踪,因为当月的当天小于所要求的月份的天数时,代码“有效”.根据我的经验,除非你绝对需要,否则最好避免使用strtotime,当你绝对需要时,你尽可能多地提供明确的信息.

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...