[英]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.