繁体   English   中英

strtotime()有bug吗?

[英]Is strtotime() having a bug?

考虑我们想要添加或减去一秒的代码:

date_default_timezone_set("Europe/Amsterdam");

$time = 1477789199;
echo $time . '  -  ' . date('r', $time) . "\n";
// 1477789199  -  Sun, 30 Oct 2016 02:59:59 +0200

这是正确的,因为此时间戳仍然在DST(夏令时/夏令时)内。

但现在让我们在时间戳整数中添加一秒,然后退出 DST:

$new = $time + 1;
echo $new . '  -  ' . date('r', $new);
// 1477789200  -  Sun, 30 Oct 2016 02:00:00 +0100

万岁! PHP看到一秒后不再有DST并显示正确的时间字符串。

但是如果我们没有在timestamp整数中添加第二个,但是我们使用strtotime()来添加一秒:

$new = strtotime('+1 second', $time);
echo $new . '  -  ' . date('r', $new);
// 1477792800  -  Sun, 30 Oct 2016 03:00:00 +0100

哎呀! 我们只用了一个多小时而不是一秒钟。 如果你加一秒,一小时,一天或一年,你总会得到一个额外的小时。 即使你增加了多年,你也只会多花一个小时,这很奇怪,因为我们每年都会进入和退出DST,但无论你添加多少年,你只能再多花一个小时

但是一旦我们在十月份退出 DST并减去一秒钟,一切都很好......

但话又说回来。 如果我们在三月份,我们刚刚进入夏令时,我们减去一秒,我们反过来观察完全相同。


等等,什么?! 那么......?

echo strtotime('+ 1 second - 1 second', 1477789199); // echoes 1477792799

哇......


对我来说,这听起来像一个bug。 或者这是'按设计'? 有人甚至知道这是否在某处记录,或者是否需要报告?

行为是“记录良好”....在测试中:

请参阅https://bugs.php.net/bug.php?id=30532 (也按预期显示您的预期结果)和相关的测试文件(断言当前行为是正确的) https://github.com /php/php-src/blob/master/ext/date/tests/bug30532.phpt

<?php date_default_timezone_set("America/New_York");

echo date('Y-m-d H:i:s T', strtotime('2004-10-31 EDT +1 hour'))."\n";
echo date('Y-m-d H:i:s T', strtotime('2004-10-31 EDT +2 hours'))."\n";
echo date('Y-m-d H:i:s T', strtotime('2004-10-31 EDT +3 hours'))."\n";
/* 2004-10-31 01:00:00 EDT
   2004-10-31 01:00:00 EST
   2004-10-31 02:00:00 EST */

echo date('Y-m-d H:i:s T', strtotime('2004-10-31 +1 hour'))."\n";
echo date('Y-m-d H:i:s T', strtotime('2004-10-31 +2 hours'))."\n";
echo date('Y-m-d H:i:s T', strtotime('2004-10-31 +3 hours'))."\n";
/* 2004-10-31 01:00:00 EDT
   2004-10-31 02:00:00 EST
   2004-10-31 03:00:00 EST */

请注意,在前一种情况下,时区(此处为: EDT )将直接传递给字符串,在后一种情况下则不是。

一般情况下, strtotime采用时间戳(即2004-10-31 - 或在您的特定情况下:传递的时间戳),转换为具有单个参数的表示,忽略DST(即个别小时,分钟,秒,日,月,年等),操作应用于它,然后转换回时间戳。

特别是:

echo date('r', strtotime('+ 0 second', 1477789199));
#> Sun, 30 Oct 2016 02:59:59 +0100

strtotime()在转换之后抛出时区,即仅占用

Sun, 30 Oct 2016 02:59:59

然后将主要适用的时区应用到您的时区位置(即Europe/Amsterdam ),最后是CET (主要!) - CEST也是可能的,但只是第二选择。

现在,回顾上面的测试,只需明确指定原始时区。

因此,如果您希望它以您需要的方式运行:

echo date('r', strtotime('CEST', 1477789199));
#> Sun, 30 Oct 2016 02:59:59 +0200
echo date('r', strtotime('CEST + 1 second', 1477789199));
#> Sun, 30 Oct 2016 02:00:00 +0100

事实上,前面加上'CEST '将是罚款,所有的时间(因为它总是会回退到CET如果CEST不匹配,并有上没有重叠CET - > CEST过渡)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM