gpt4 book ai didi

php - DateTime 在 DST 冬季更改期间更改时间戳

转载 作者:可可西里 更新时间:2023-10-31 23:17:52 24 4
gpt4 key购买 nike

今天在 PHP DateTime::setTimestamp() 行为中遇到了有趣的特性(?)。在冬季 DST 更改期间,当 1 小时重复两次时,PHP 将时间戳转换为始终是第二个小时。考虑以下示例:

<?php

$date = new \DateTime("now", new \DateTimeZone("UTC"));
//2018-10-28T01:30:00 UTC, in London DST happens
$date->setTimestamp(1540686600);

echo $date->getTimestamp() . "\n";
//1540686600
echo $date->format('c') . "\n";
//2018-10-28T00:30:00+00:00

$date->setTimezone(new \DateTimeZone("Europe/London"));

echo $date->getTimestamp() . "\n";
//1540690200

$date->setTimezone(new \DateTimeZone("UTC"));

echo $date->getTimestamp() . "\n";
//1540690200

echo $date->format('c') . "\n";
//2018-10-28T01:30:00+00:00

查看source PHP 尝试将时间戳转换为本地时间 (o_O)。那么两个问题:

  • 为什么要转换时间戳?时间戳始终采用 UTC,并且应该与本地时间/时区无关
  • 是否有任何简单的解决方案可以在 DateTime 对象中同时保留时区 ID 和预期时间戳? (我知道有可能将所有内容都保存在 UTC 中并仅在显示时转换为本地时区)

找到 possible bug用 PHP 提交

UPD 2016-01-04(UTC):

将问题缩小到 DateTime::getTimestamp()。考虑以下代码:

<?php

$date = new \DateTime("now", new \DateTimeZone("UTC"));
//2018-10-28T00:30:00 UTC
$date->setTimestamp(1540686600);
echo $date->format('c') . "\n"; //2018-10-28T00:30:00+00:00

$date->setTimezone(new \DateTimeZone("Europe/London"));
echo $date->format('c') . "\n"; //2018-10-28T01:30:00+01:00

$date->setTimezone(new \DateTimeZone("UTC"));
echo $date->format('c') . "\n"; //2018-10-28T00:30:00+00:00
echo $date->getTimestamp() . "\n"; //1540686600

此处时间戳未更改,代码按预期工作。以下与原始示例中给出的类似代码已损坏:

<?php

$date = new \DateTime("now", new \DateTimeZone("UTC"));
//2018-10-28T00:30:00 UTC
$date->setTimestamp(1540686600);
echo $date->format('c') . "\n"; //2018-10-28T00:30:00+00:00

$date->setTimezone(new \DateTimeZone("Europe/London"));
echo $date->format('c') . "\n"; //2018-10-28T01:30:00+01:00
//-------------- the only line that was added ------------------
echo $date->getTimestamp() . "\n"; //1540690200
//-------------- end of added line -----------------------------

$date->setTimezone(new \DateTimeZone("UTC"));
echo $date->format('c') . "\n"; //2018-10-28T01:30:00+00:00
echo $date->getTimestamp() . "\n"; //1540690200

最佳答案

你说:

Timestamp is always in UTC and should be local time, timezone agnostic

该声明自相矛盾。时间戳是 UTC,是的,但这不是本地时间或时区不可知论。

换句话说,时间戳 始终指代特定的瞬间。 本地时间 可能不明确,但时间戳则不然。如果您想要模糊本地时间的第一个实例,请指定一个小时前的时间戳。

但是,您的数据有点不正确。您指定的时间戳 1540686600 实际上不是 1:30 UTC,而是对应于 2018-10-28T01:30:00+01:00。因此,这确实是回退 DST 转换当天 第一次 1:30 的出现。第二次出现是 2018-10-28T01:30:00+00:00,对应于 1540690200

关于你的第二个问题:

is there any simple solution to keep both timezone id and intended timestamp in DateTime object?

这就是 DateTime 在 PHP 中的工作方式。它由一个内部时间戳和一个关联的时区组成。这正是您调用 setTimezone 时显示的内容。

关于php - DateTime 在 DST 冬季更改期间更改时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34533604/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com