PHP time() 和 DST 问题结束 - DST 结束后 1 小时

Posted

技术标签:

【中文标题】PHP time() 和 DST 问题结束 - DST 结束后 1 小时【英文标题】:PHP time() and end of DST issue - 1 hour after end of DST 【发布时间】:2013-09-29 00:59:05 【问题描述】:

我已经这样定义了这段代码(为了清楚起见,简化版):

$fifteenMinsLater = strtotime('+900 second', time());
$now = time();
 if ( $now > $fifteenMinsLater )     
    mtrace("This should NEVER happen"); 
 
 else 
    mtrace("This should always be the case");
 

2013 年 3 月 11 日凌晨 2:00,美国/纽约的夏令时结束,时钟倒转一小时到凌晨 1:00。

当我在 2013 年 3 月 11 日和凌晨 1:00 到凌晨 2:00 之间的 DST 结束后(即凌晨 2:00 变为凌晨 1:00)运行上述代码时:

This should NEVER happen

被打印出来。但是,在 DST 转换之前或新的凌晨 2:00 之后的任何时间都可以。

这导致了一个重大错误,导致用户尝试访问使用上述代码的函数在 DST 转换后的一小时内惨遭失败。

php 5.2.11。

有什么想法吗?

【问题讨论】:

你确定你没有过分简单化吗? strtotime & time 返回 unix 时间戳,据了解,它不知道 DST/不会意外倒计时 3600 秒。您是在比较这些时间戳的表示,而不是原始整数时间戳本身吗? AFAIK,只有闰秒会影响 unix 时间戳。 $now 和 $fifteenMinsLater 的回声将大大有助于解决这个问题。 Site 3v4l.org 非常适合测试不同的 PHP 版本。只有版本 5.0.0 to 5.0.2 返回无效比较。 【参考方案1】:

strtotime() 和 PHP 中的其他日期函数不考虑时区。 DateTime() 确实:

$fifteenMinsLater = new DateTime();
$fifteenMinsLater->modify('+15 minutes');
$now = new DateTime();

if ( $now > $fifteenMinsLater )     
   mtrace("This should NEVER happen"); 

else 
   mtrace("This should always be the case");

以下是 PHP 5.5 中的操作方法:

$now = new DateTimeImmutable();
$fifteenMinsLater = $now->modify('+15 minutes');

if ( $now > $fifteenMinsLater )     
   mtrace("This should NEVER happen"); 

else 
   mtrace("This should always be the case");

【讨论】:

是的,他们确实没有考虑时区,但这就是重点。他们使用UTC unix时间。因此,向同一个 time() 函数添加 15 分钟应该可以作为派生时间变量($now 和 $fifteenMinLater)工作,但它们是 int unix 时间戳。我会给你的答案投票(如果我有足够的代表),因为在 PHP 5.3.6 中使用上面的第一个代码会产生正确的结果。然而,在 PHP 5.2.17 上使用它显示了同样的问题,这让我相信 PHP 5.2.x 中存在一个继承错误。非常感谢!

以上是关于PHP time() 和 DST 问题结束 - DST 结束后 1 小时的主要内容,如果未能解决你的问题,请参考以下文章

DST 和 PHP 日期和时间戳

DST 结束时的 Laravel Carbon addHour()

org.joda.time |夏令时 (DST) 和本地时区偏移

PHP获取今天开始和结束的时间戳

php获取当天的开始时间和结束时间

Python 时间库:如何使用 strptime 和 strftime 保存 dst