Php 是否可以在夏令时更改时将filemtime与strtotime进行比较?

Php 是否可以在夏令时更改时将filemtime与strtotime进行比较?,php,dst,Php,Dst,我有一些PHP代码来发送警告,并在源数据文件过期时自动关闭服务。这是通过以下比较完成的: 警告: filemtime($file_location)sub(新日期间隔('PT1H'); 回显'sub-PT1H:',$dt->getTimestamp(),,,,,“,$dt->格式('Y-m-dh:i:s'),”\n”; //14578560602016-10-30 03:01:00,正确 回显“\n\n”; echo'TS',$current\u timestamp,,,,,,,,日期('Y-m

我有一些PHP代码来发送警告,并在源数据文件过期时自动关闭服务。这是通过以下比较完成的:

警告:
filemtime($file_location)

考虑停止服务:
filemtime($file_location)

在夏令时开始时,从CDT凌晨3:00开始的1小时内,此错误报告文件已超过15分钟。在一小时结束时,它还错误地报告文件已超过1小时。CDT凌晨4:00,一切恢复正常

关于filemtime()或strotime()函数,是否有什么我不知道的东西可以解释这种行为?据我所知,两者都返回UNIX时间戳,而且时间戳定义为UTC,所以我不确定是什么导致了这个问题

根据目前的答案,我在我们的服务器上运行了此测试:

`

for($i=1;$i setTimestamp($current_timestamp);
$dt->sub(新日期间隔('PT1H');
回显'sub-PT1H:',$dt->getTimestamp(),,,,,“,$dt->格式('Y-m-dh:i:s'),”\n”;
//14578560602016-10-30 03:01:00,正确
回显“\n\n”;
echo'TS',$current\u timestamp,,,,,,,,日期('Y-m-d H:i:s',$current\u timestamp),“\n”;
回显“\n\n”;
}
`

-3600s:14578488002016-03-13 00:00:00

-1小时:14578488002016-03-13 00:00:00

子PT1H:14578488002016-03-13 00:00:00

TS 14578524002016-03-13 01:00:00

-3600s:14578524002016-03-13 01:00:00

-1小时:14578560002016-03-13 03:00:00

子PT1H:14578560002016-03-13 03:00:00

TS 14578560002016-03-13 03:00:00

-3600s:14578524002016-03-13 01:00:00

-1小时:14578560002016-03-13 03:00:00

子PT1H:14578560002016-03-13 03:00:00

TS 14578560002016-03-13 03:00:00

-3600s:14578560002016-03-13 03:00:00

-1小时:14578560002016-03-13 03:00:00

子PT1H:14578560002016-03-13 03:00:00


TS 14578596002016-03-13 04:00:00这让人非常困惑。在我的时区,夏令时从3月27日开始,以下所有表达式都返回相同的UNIX时间戳:

var_dump(strtotime("27 March 2016 02:00"));
var_dump(strtotime("- 60 minute", strtotime("27 March 2016 02:00")));
var_dump(strtotime("- 1 hour", strtotime("27 March 2016 02:00")));
var_dump(strtotime("27 March 2016 02:00 - 1 hour"));
var_dump((new DateTime("27 March 2016 02:00"))->format("U"));
var_dump((new DateTime("27 March 2016 02:00"))->sub(new DateInterval("PT1H"))->format("U"));
如果我仔细想一想,我可能会相信这是预期的行为。3月27日01:00在这里并不存在。但这肯定不是直觉

更令人困惑的是,从02:00减去15分钟会得到一个未来的答案,即02:45。即使第一个结果有点道理,如果你眯着眼睛看得够多的话,这个结果一定是一个错误

关于这一点,已经有近4年没有被提及了


这就给了您两个选择。您可以在代码中添加一个
if
子句,如果初始减法没有减少时间戳,则减去2小时或75分钟。或者您可以简单地从当前时间戳中减去3600秒或900秒,而不是使用
strotime
。这两种方法都不是特别优雅的,但我们可以这样做e、

似乎
strotime
不够聪明,无法在操作相对值时考虑DST更改:

// let's say current time is this:
date_default_timezone_set('Europe/Berlin');
$current_timestamp = strtotime('2016-10-30 01:59:00'); // 1477785540

// DST ends at 03:00 that day, so 120 minutes later the time should be 02:59
$ts = $current_timestamp + 2*60*60;
echo $ts, ", ", date('Y-m-d H:i:s', $ts), "\n";
// 1477792740, 2016-10-30 02:59:00, correct

// now let's test strtotime with +2 hours
$ts = strtotime('+2 hours', $current_timestamp);
echo $ts, ", ", date('Y-m-d H:i:s', $ts), "\n";
// 1477796340, 2016-10-30 03:59:00, completely wrong

// DateTime implementation seems smarter:
$dt = new DateTime();
$dt->setTimestamp($current_timestamp);
$dt->add(new DateInterval('PT2H'));
echo $dt->getTimestamp(), ", ", $dt->format('Y-m-d H:i:s');
// 1477792740, 2016-10-30 02:59:00, correct

在您的特定情况下,我只需直接比较时间戳(显然,差异以秒为单位),但是使用
DateTime
TimeInterval
也是一种选择。

开放式PHP错误可能是问题的根源,尽管我仍然不明白发生了什么。在上面的进一步测试中,从时间戳中减去3600得到的答案是正确的,而其他答案减去en时是错误的从DT中的某个时间返回ST的时间。因此,凌晨1点到1点总是午夜,凌晨4点到1点总是凌晨3点。凌晨2点和凌晨3点是同一时间。时间戳-3600正确返回凌晨1点,而在这两种情况下使用strotime或DateInterval错误返回凌晨3点(即不减去时间)。在我的测试中(添加到问题中,因为注释的代码太多了),使用“-1小时”和
strotime
和“PT1H”使用
DateTime
给出相同的时间戳。不仅彼此相同,还与我调整的基准时间戳相同。至少在问题时间内。但是,减去总秒数会给出不同的时间戳。
// let's say current time is this:
date_default_timezone_set('Europe/Berlin');
$current_timestamp = strtotime('2016-10-30 01:59:00'); // 1477785540

// DST ends at 03:00 that day, so 120 minutes later the time should be 02:59
$ts = $current_timestamp + 2*60*60;
echo $ts, ", ", date('Y-m-d H:i:s', $ts), "\n";
// 1477792740, 2016-10-30 02:59:00, correct

// now let's test strtotime with +2 hours
$ts = strtotime('+2 hours', $current_timestamp);
echo $ts, ", ", date('Y-m-d H:i:s', $ts), "\n";
// 1477796340, 2016-10-30 03:59:00, completely wrong

// DateTime implementation seems smarter:
$dt = new DateTime();
$dt->setTimestamp($current_timestamp);
$dt->add(new DateInterval('PT2H'));
echo $dt->getTimestamp(), ", ", $dt->format('Y-m-d H:i:s');
// 1477792740, 2016-10-30 02:59:00, correct