使用PHP DateTime解析时区PST到PDT(GMT -8到GMT -7)

时间:2016-09-28 01:08:31

标签: php datetime timezone

我无法使用PHP DateTime将GMT -8时区(PST)收到的日期转换为时区GMT -7(PDT)的人类可读格式。

以下是一个例子:

$tz = new DateTimeZone('America/Los_Angeles');  
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00");
$saleEndDate->setTimezone($tz);
echo $saleEndDate->format('Y-m-d H:i:s');

以上代码的输出为: 2016-11-07 17:30:00 。但是,它应显示 2016-11-07 18:30:00 ,因为America/Los_Angeles现在处于夏令时(GMT -7,PDT)。

根据我在DateTime docs中所阅读的内容,new DateTime命令应该能够解释字符串2016-11-07T17:30:00-08:00具有GMT -8时区:

  

时间参数包含UNIX时间戳(例如946684800)或指定时区(例如2010-01-28T15)时,将忽略时区参数和当前时区:00:00 + 02:00)

即便如此,我认为DateTime无法正确识别GMT-8。

有谁知道正确转换时区需要什么方法?

更新

我还尝试将DateTimeZone作为第二个参数传递给DateTime构造函数,但也无济于事:

$tz = new DateTimeZone('America/Los_Angeles');  
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00", new DateTimeZone("America/Los_Angeles"));
$saleEndDate->setTimezone($tz);
echo $saleEndDate->format('Y-m-d H:i:s');

也不起作用:

$tz = new DateTimeZone('America/Los_Angeles');  
$saleEndDate = new DateTime("2016-11-07T17:30:00", new DateTimeZone("PST"));
$saleEndDate->setTimezone($tz);
echo $saleEndDate->format('Y-m-d H:i:s');

也不起作用:

$tz = new DateTimeZone("PDT");  
$saleEndDate = new DateTime("2016-11-07T17:30:00", new DateTimeZone("PST"));
$saleEndDate->setTimezone($tz);
echo $saleEndDate->format('Y-m-d H:i:s');

2 个答案:

答案 0 :(得分:2)

不是最伟大的,但这是我能想到的唯一方法

$tz = new DateTimeZone('America/Los_Angeles');  
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00");
$saleEndDate->setTimezone($tz);
$stamp = $saleEndDate->format('U');
$zone = $tz->getTransitions($stamp, $stamp);
if(!$zone[0]['isdst']) $saleEndDate->modify('+1 hour');
echo $saleEndDate->format('Y-m-d H:i:s');

我在这里做的是使用DateTimeZone::getTransitions function来确定您提供的日期是否为DST。如果不是,我们加1小时。请注意,这不会更改时区,它只会更正DST转换

You can see it in action here

答案 1 :(得分:1)

DateTime正在运作。除非你在一个区域内观察到与更大区域不同的DST,America/Los_Angeles在11月6日(2016年)离开DST(PDT-> PST)。

https://www.timeanddate.com/news/time/usa-canada-end-dst-2016.html

timezeonedb你可以通过搜索数组中的特定日期/时间(Machavity所做的)检查它使用的日期,并得到它不在DST中然后继续修改它的事实手动。这不是一个答案,因为它会最终失败,除非你手动添加一个截止时间让手动修正停止。

检查日期的过渡日期显示:

date_default_timezone_set('America/Los_Angeles');
$theDate = new DateTime("2016-11-07T17:30:00",new DateTimeZone("America/Los_Angeles"));
$theDateBefore = new DateTime("2016-03-01");
$theDateAfter = new DateTime("2017-03-15");
echo "<pre>";
print_r( $theDate->getTimezone()->getTransitions(
     $theDateBefore->getTimestamp(),$theDateAfter->getTimestamp()));
echo "</pre>";

产生一个4:

的数组
Array
(
    [0] => Array
        (
            [ts] => 1456819200
            [time] => 2016-03-01T08:00:00+0000
            [offset] => -28800
            [isdst] => 
            [abbr] => PST
        )

    [1] => Array
        (
            [ts] => 1457863200
            [time] => 2016-03-13T10:00:00+0000
            [offset] => -25200
            [isdst] => 1
            [abbr] => PDT
        )

    [2] => Array
        (
            [ts] => 1478422800
            [time] => 2016-11-06T09:00:00+0000
            [offset] => -28800
            [isdst] => 
            [abbr] => PST
        )

    [3] => Array
        (
            [ts] => 1489312800
            [time] => 2017-03-12T10:00:00+0000
            [offset] => -25200
            [isdst] => 1
            [abbr] => PDT
        )

)

数组[0]是theDateBefore生效的时区,您可以看到日期更改对您的时间有效。

您的销售日期在从PDT更改为PST之后。

要让代码返回调整后的日期/时间,您需要手动更改它。按照被接受的方式进行会产生错误的结果。正如我所提到的,你需要用你想要强制执行自定义时区的日期来包围它。