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

DateTime object not bound by its timestamp?

DateTime 对象 不受其时间戳的约束吗? 或者 getTimestamp() 是否有某种副作用DST 更改时使用?

详情
当设置 DST 上的 DateTime 对象的时间戳时(意味着格式化时间同时存在 before/after 更改时钟)返回的时间戳与设置的时间戳不同。

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

为什么打印的值不相等?

\DateTime 对象不保留时间戳而是本地时间,并在timestamp getter and timestamp setter.

中进行转换

当关闭 DST 时,每年都会产生一次副作用,因为时间戳范围 1319932800..1319936400 和 1319936400..1319940000 解析为相同的本地时间:
https://www.epochconverter.com/timezones?q=1319936399&tz=Europe%2FBerlin https://www.epochconverter.com/timezones?q=1319939999&tz=Europe%2FBerlin

首先,unix 时间戳始终是 UTC,因此它没有时区和 DST。

另一方面,DateTime 对象仅存储 当地时间 ("local" 表示在 DateTime实例).

因此在设置时间戳之前,您应该将时区设置为 +00:00UTC 以避免不必要的时间转换和 DST 猜测.

您有两个选择:

1。通过 DateTime

的构造函数设置时间戳

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

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

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

信息:在这种情况下,构造函数的时区参数总是会被覆盖。

2。调用前设置时区 setTimestamp()

在调用 setTimestamp():

之前使用 DateTimeZone('+00:00')DateTimeZone('UTC') 时区调用 setTimezone()
$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 时间戳转换为本地时间时) 时区将再次变得有趣。