Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php DateTime在DST冬季更改期间更改时间戳_Php_Dst - Fatal编程技术网

Php DateTime在DST冬季更改期间更改时间戳

Php DateTime在DST冬季更改期间更改时间戳,php,dst,Php,Dst,今天在PHPDateTime::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

今天在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
在这里,时间戳并没有改变,代码按预期工作。以下代码与原始示例中给出的代码相似,但已被破坏:

<?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为单位,并且应该是本地时间,时区不可知

那句话本身就有矛盾。时间戳是以UTC为单位的,但这不是本地时间或时区不可知的

换句话说,时间戳总是指一个特定的时间瞬间。本地时间可能不明确,但时间戳不明确。如果需要不明确的本地时间的第一个实例,请指定一个时间戳,该时间戳早一个小时

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

关于你的第二个问题:

有没有简单的解决方案可以在DateTime对象中同时保留时区id和预期的时间戳


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

时显示的内容,PHP时区处理完全是垃圾,已经花费了我好几天的时间。考虑<代码>保持在UTC中的所有内容,只在显示严重时转换到本地时区。参见@ Axell,而我个人认为PHP是“完全垃圾”,当涉及时区时,PHP实际上与其他一些语言相比有了提升。考虑Python,它是一种高级语言(IMHO),但是需要库支持时区,并且有一些API细微差别为开发人员创建陷阱(比如pytz本地化和tz替换)。此外,当您进入诸如计划安排等高级场景时,UTC所有内容的论点都不成立。@MattJohnson我只不同意计划部分:至少为了精确起见,我曾经将所有内容转换为UTC,并让计划程序也以UTC运行。@Axel-大多数人工事件都基于本地时间。考虑一下,如果你只用UTC设置一个每日闹钟,那么它会提前一个小时或一个小时后切换到/从夏时制。(). 另请参见:“
UTC
”和“
Europe/London
”之间的区别是什么?AFAIK Greenwich与伦敦相同?@AxelAmthor Europe/London遵守DST规则,而UTC根据定义则不遵守。完全明白。伦敦(和格林威治)仅在一年中的部分时间遵循格林威治标准。另一部分是英国夏令时(BST),使用UTC+01:00。感谢您的评论!是的,我把UTC时间贴错了。修正了。说时间戳是时区不可知的,我的意思是,无论何时更改时区,时间戳都应该保持不变,因为它总是在UTC中。这就是PHP让我吃惊的地方。当我将第一次出现的时间设置为01:30,对应UTC中的特定时间时,我希望无论何时时区为set@mente-是的,它看起来确实像一只虫子。我以前没有注意到,但即使在您的代码中,调用
setTimezone
将区域从UTC更改为伦敦,也不会影响
getTimestamp
返回的值。我想我必须同意Axel关于PHP与时区的混乱的观点。其目的是好的,但看起来实现有缺陷。
<?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