DateTime对象不受其时间戳的约束?

时间:2017-04-05 07:35:47

标签: php datetime dst

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

为什么打印值不相等?

2 个答案:

答案 0 :(得分:3)

\DateTime对象不保留时间戳,但保留当地时间,并在timestamp gettertimestamp 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猜测。

您有两种选择:

1。通过DateTime

的构造函数设置时间戳

当构造函数在第一个参数中获得时间戳(以@开始)时,构造函数将覆盖默认时区并显式设置为 +00:00 :< / p>

$set_timestamp = 1319932800;
$date = new DateTime('@' . $set_timestamp);

print($set_timestamp . "\n");
print($date->getTimestamp() . "\n");

信息:在这种情况下,构造函数的timezone参数将被覆盖。

2。在呼叫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时间戳转换为本地时间时)时区将再次变得有趣。