DateTime在DST冬季更改期间更改时间戳 [英] DateTime alters timestamp during DST winter change

查看:82
本文介绍了DateTime在DST冬季更改期间更改时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Today encountered interesting feature (?) in PHP DateTime::setTimestamp() behavior. During winter DST changes, when 1 hour repeats twice, PHP converts timestamp to always be the second hour. Consider following example:

<?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

看看 PHP尝试将时间戳转换为当地时间(o_O)。所以有两个问题:

Looking at source PHP tries to convert timestamp to local time (o_O). So two questions:


  • 为什么要转换时间戳?时间戳始终使用UTC,并且应该与本地时间/时区无关。

  • 是否有任何简单的解决方案将时区ID和预期时间戳都保留在 DateTime 对象? (我知道可以将所有内容保留在 UTC 中,并且仅在显示时才转换为本地时区)

  • why there's conversion of timestamp? Timestamp is always in UTC and should be local time/timezone agnostic
  • is there any simple solution to keep both timezone id and intended timestamp in DateTime object? (I am aware of possibility to keep everything in UTC and convert to local timezone only when showing)

找到了用PHP归档的可能错误

UPD 2016-01-04(以UTC为单位)

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

Narrowed down problem to DateTime::getTimestamp(). Consider following code:

<?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

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

Here timestamp is not altered and code works as expected. Following code that is similar and was given in original example is broken:

<?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


推荐答案

您说:


时间戳始终为UTC,并且应为本地时间,与时区无关

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

该陈述本身与之冲突。时间戳以UTC表示,是的,但这与本地时间或时区无关。

That statement is in conflict with itself. Timestamps are in UTC, yes, but that is not local time or time zone agnostic.

换句话说,时间戳始终是指特定时间点。 本地时间可能不明确,但时间戳并非如此。如果您想要本地时间模棱两可的第一个实例,请指定一个小时前的时间戳。

Put another way, a timestamp always refers to a specific instant in time. A local time might be ambiguous, but a timestamp is not. If you wanted the first instance of the ambiguous local time, then specify a timestamp that is an hour earlier.

但是,您的数据略有错误。您指定的时间戳 1540686600 实际上不是1:30 UTC,而是对应于 2018-10-28T01:30:00 + 01: 00 。因此,确实是后备DST转换当天发生的第一次 1:30。第二次出现是 2018-10-28T01:30:00 + 00:00 ,它对应于 1540690200

However, your data is slightly incorrect. The timestamp you specified, 1540686600, is actually not 1:30 UTC but rather it corresponds to 2018-10-28T01:30:00+01:00. Therefore, it is indeed the first occurrence of 1:30 on the day of the fall-back DST transition. The second occurrence would be 2018-10-28T01:30:00+00:00, which corresponds to 1540690200.

关于第二个问题:


有没有简单的解决方案可以同时保留这两个问题

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

这已经是 DateTime 的工作原理了在PHP中。它由一个内部时间戳和一个关联的时区组成。这就是您调用 setTimezone 时所显示的内容。

That's already how DateTime works in PHP. It consists of an internal timestamp, and an associated time zone. That's exactly what you're showing when you call setTimezone.

这篇关于DateTime在DST冬季更改期间更改时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆