标准和日光时间的DateTimeZone和UTC偏移量

时间:2014-10-19 17:48:49

标签: php datetime timezone utc timezone-offset

我有一个问题是从PHP DateTimeZone和底层数据库中获取UTC偏移信息。我接近每个DT / ST对,但通常少一小时(DT)的时区不是。

例如(source):

东部夏令时 EDT ),当观察夏令时(春/夏)时,比世界协调时间晚4小时( UTC-04:00 )。

东部标准时间 EST ),当观察标准时间(秋/冬)时,比世界协调时间晚5小时( UTC-05:00 )。

到目前为止,我获得了UTC偏移量(在DateTimeZone::getOffset中对GMT表示,但我认为这是相同的),如下面的代码所示:

$zones = ['EDT', 'EST'];

foreach ($zones as $zone) {
    // get offset
    $timezone = new DateTimeZone($zone);
    $offset = $timezone->getOffset(new DateTime(null, $timezone));

    printf("%s (%s) %s\n", $zone, $timezone->getName(), format_offset($offset));
}

示例输出(full example,我使用PHP 5.6.1RC1):

EDT (EDT) -0500
EST (EST) -0500

这两个时区实际上是示范性的,我也希望与其他时区一起做,但是我不想对偏移进行硬编码,而是希望用PHP来解决这个问题。强> DateTimeZone

当我看到output across multiple PHP versions时,我可能会遇到一个错误,看起来HHVM没有通过转置它来解决这个问题:

Output for hhvm-3.2.0 - 3.3.0

EDT (America/New_York) -0400
EST (EST) -0500

Output for 5.5.10 - 5.6.2, php7@20140507 - 20141001

EDT (EDT) -0500
EST (EST) -0500

Output for 5.2.0 - 5.5.9

EDT (America/New_York) -0400
EST (America/New_York) -0400

是否存在跨PHP版本兼容的方式?通常情况下,DateTimeZone并没有摆弄那么深,到目前为止,我觉得它会很好用。

2 个答案:

答案 0 :(得分:3)

PHP使用标准IANA tz database。您可以找到支持的时区列表on Wikipediain the PHP documentation

特别是,您会发现像"EST"这样的值仅用于向后兼容。您可以在this page文档中看到,使用该格式的时区有一个关于的大红色警告。虽然"EST"位于已弃用区域列表中,但"EDT"不是。

通常,时区缩写会使标识符变差,因为模糊性太多。考虑this list of abbreviations,它有两种不同的EDT解释,5种不同的CST解释,以及许多其他冲突。

还要考虑像"America/New_York"这样的完整标识符准确地表示EST和EDT,并且具有何时在它们之间转换的所有知识 - 包括历史差异。

在您提供的代码中,您要求PHP分别为EST和EDT提供当前偏移量。这没有意义,因为EDT仅在一年中的部分时间生效,并且EST和EDT不能在同一位置同时生效。相反,使用"America/New_York"偏移量,并提供特定时间来获取当时的偏移量。

如果您只想要每个区域的标准和日光偏移,您可以测试当年1月1日和7月1日的午夜。标准偏移量以较低者为准。如果它们相同,那么(通常)时区不使用夏令时。

答案 1 :(得分:2)

并非所有PHP DateTimeZone在ctor的$timezone参数中作为字符串接受的时区确实具有稳定的UTC偏移量。从技术上讲,那两个 EDT EST ,不是真正的时区,时区是东部时区 ET tz database中的美国/东部 America / New_York ,这是数据源PHP DateTimeZone 经营。

+------------------+--------------------+-----------------------------------------+
| string           | getName()          | offsets                                 |
+------------------+--------------------+-----------------------------------------+
| America/New_York | (America/New_York) | -0500 / -0400 (2012-01-01 / 2012-06-30) |
| US/Eastern       | (US/Eastern)       | -0500 / -0400 (2012-01-01 / 2012-06-30) |
| EDT              | (EDT)              | -0500 / -0500 (2012-01-01 / 2012-06-30) |
| EST              | (EST)              | -0500 / -0500 (2012-01-01 / 2012-06-30) |
+------------------+--------------------+-----------------------------------------+

所以特别是我的问题中的那两个 EDT EST 不能正常工作,因为它们分别代表标准和夏令时,而PHP的 DateTimeZone 确实代表两者。因此,UTC偏移是不明确的。 PHP manual documents仅出于向后兼容性原因而接受这些RFC2822 p. 32,并且不应与 DateTimeZone 类一起使用。页面上的用户注释说得很好:

  

不要使用'EST',至少在PHP 5.3.3中它与'EST5EDT'相同,而不是严格的标准时间。我发现将时间解释为标准时间的唯一可靠方法是使用UTC相对格式,例如:

$dateObject = date_create("2013-06-30 07:00:00-0500");

这也是我使用的规范( 4.3。过时的日期和时间; {{3}})所说的,使用这些区域已经过时了。我只是希望我能够免费为UTC-offset地图创建一个时区:

EDT is semantically equivalent to -0400
EST is semantically equivalent to -0500
CDT is semantically equivalent to -0500
CST is semantically equivalent to -0600
MDT is semantically equivalent to -0600
MST is semantically equivalent to -0700
PDT is semantically equivalent to -0700
PST is semantically equivalent to -0800

但这不是一个很大的名单。