DateTime
对象是否受其时间戳限制?或者在DST上使用时 getTimestamp()有某种副作用改变吗
详情
设置DateTime
上的DST
对象的时间戳时(意味着在更改时钟之前/之后存在格式化时间),返回的时间戳与设置的时间戳不同。
$ php --version
PHP 7.1.3 (cli) (built: Mar 17 2017 16:59:59) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
重现
请考虑以下php
脚本:
date_default_timezone_set('Europe/Berlin');
$date = new DateTime();
$set_timestamp = 1319932800;
$date->setTimestamp($set_timestamp);
$get_timestamp = $date->getTimestamp();
fwrite(STDERR, $set_timestamp . "\n"); // 1319932800
fwrite(STDERR, $get_timestamp . "\n"); // 1319936400 **(WHY IS THIS DIFFERENT?)**
为什么打印值不相等?
答案 0 :(得分:3)
\DateTime
对象不保留时间戳,但保留当地时间,并在timestamp getter和timestamp setter中进行转换。
由于两个时间戳范围1319932800..1319936400和1319936400..1319940000都解析为相同的当地时间,因此每年关闭DST时会产生一次副作用: https://www.epochconverter.com/timezones?q=1319936399&tz=Europe%2FBerlin https://www.epochconverter.com/timezones?q=1319939999&tz=Europe%2FBerlin
答案 1 :(得分:3)
首先,unix时间戳始终为UTC,因此它没有时区和DST。
另一方面,DateTime
对象只存储本地时间 (" local"表示DateTime
中设置的时区实例)
因此,在设置时间戳之前,应将时区设置为 +00:00 或 UTC ,以避免不必要的时间转换和DST猜测。
您有两种选择:
DateTime
当构造函数在第一个参数中获得时间戳(以@
开始)时,构造函数将覆盖默认时区并显式设置为 +00:00 :< / p>
$set_timestamp = 1319932800;
$date = new DateTime('@' . $set_timestamp);
print($set_timestamp . "\n");
print($date->getTimestamp() . "\n");
信息:在这种情况下,构造函数的timezone参数将被覆盖。
setTimestamp()
在致电setTimezone()
之前,使用DateTimeZone('+00:00')
或DateTimeZone('UTC')
时区致电setTimestamp()
:
$set_timestamp = 1319932800;
$date = new DateTime();
$date->setTimezone(new DateTimeZone('UTC'));
$date->setTimestamp($set_timestamp);
print($set_timestamp . "\n");
print($date->getTimestamp() . "\n");
当然,这两种情况的输出都是:
1319932800
1319932800
在这些情况下,date_default_timezone_set()
是不必要的,因为您不想在当地时间做任何事情。
但是,当您想要以人类可读格式打印$date
时(因此当您将unix时间戳转换为本地时间时)时区将再次变得有趣。