首页 > 解决方案 > PHP:转换后一小时从 Dailight Savings Time 中减去 1 小时

问题描述

我在 PHP 中遇到了一件奇怪的事情。在时区中,Europe/Oslo我从时间戳中减去了一小时2020-03-29 03:00:00(这正是 Dailight Savings Time shift 发生的时间),结果是完全相同的时间戳2020-03-29 03:00:00!它应该导致2020-03-29 01:00:00. 怎么没有?

一直到2020-03-29 03:59:59它在减去一小时时返回完全相同的时间戳(尝试了sub()modify())。之后的下一秒,它正确地导致2020-03-29 03:00:00.

你可以像这样重现它:

date_default_timezone_set('Europe/Oslo');
echo (new \DateTime('2020-03-29 03:00:00'))->sub(new \DateInterval('PT1H'))->format('Y-m-d H:i:s');

我已经在 PHP 7.1.33、7.3.10 和 7.3.18 中对此进行了测试。

PS。增加 1 小时2020-03-29 01:00:00确实可以正确给出2020-03-29 03:00:00

标签: phpdatetimedst

解决方案


虽然我同意这是不良/错误的行为,但您可以通过严格只在 UTC 中存储或计算日期来避免它。考虑时区仅用于显示目的,您将避免很多麻烦。

例如:

// input
$utc     = new DateTimeZone('UTC');
$user_tz = new DateTimeZone('Europe/Oslo');
$input   = new DateTime('2020-03-29 03:00:00', $user_tz);
$storage = (clone $input)->setTimezone($utc);
var_dump(
    $input->format('c'),
    $storage->format('c')
);

// compute
$interval = new DateInterval('PT1H');
$storage->sub($interval);
var_dump(
    $storage->format('c')
);

// display
$display = (clone $storage)->setTimezone($user_tz);
var_dump(
    $display->format('c')
);

输出:

string(25) "2020-03-29T03:00:00+02:00"
string(25) "2020-03-29T01:00:00+00:00"
string(25) "2020-03-29T00:00:00+00:00"
string(25) "2020-03-29T01:00:00+01:00"

推荐阅读