PHP DateTime转换问题

时间:2015-03-14 13:23:21

标签: php timezone

我将DateTime从莫斯科时区转换为纽约时区时出现问题。这是我的测试脚本:

$year = 2015;
$month = 3;
$tzMoscow = new DateTimeZone('Europe/Moscow');
$tzNewYork = new DateTimeZone('America/New_York');
$startDate = DateTime::createFromFormat('Y-n-d', "$year-$month-01", $tzMoscow);
echo $startDate->format('Y-m-d H:i:s')."\n"; // 2015-03-01 16:16:05
$startDate = DateTime::createFromFormat('Y-n-d', "$year-$month-01", $tzNewYork);
echo $startDate->format('Y-m-d H:i:s') . "\n"; // 2015-03-01 09:16:05
$startDate->setTimezone($tzMoscow);
echo $startDate->format('Y-m-d H:i:s') . "\n"; // 2015-03-01 17:16:05

第三个输出不正确,时间应为16:16:05。我做错了什么,或者这是php中的错误?

3 个答案:

答案 0 :(得分:2)

我想我已经明白了。问题是您没有指定时间,因此createFromFormat正在使用“当前系统时间”:

  

如果格式不包含该字符!那么生成时间中未以格式指定的部分将被设置为当前系统时间。

现在使用“当前系统时间”在纽约时区创建时间是什么意思,当时区在指定日期(3月1日)和当前日期(3月14日)之间更改了UTC偏移)?它是3月1日的UTC-5,由于夏令时,它现在是UTC-4。

我相信PHP会在指定的时区(当您运行该代码时为9:16)使用当前时间,然后将其用作指定日期的时间。因此,我们最终将于2015年3月1日,纽约时间09:16 - 或3月1日14:16 UTC,即莫斯科时间3月1日17:16。

这与您运行代码时的莫斯科当前时间不一样,即16:16。

基本上,你应该尽量不这样做 - 或者预计会发生这样的问题。考虑一下你真正试图表示的时间,记住在特定时区内,抵消会随着时间的推移而变化。我无法真正建议您应该的代码,因为我们不知道您要实现的目标 - 但是将当前时间用于其他日期< / em>肯定会导致这个问题。

答案 1 :(得分:0)

我也相信这是DST的一个问题,于3月8日在纽约时区发生变化。我将日期格式扩展到Y-m-d H:i:s U I以包含unix时间戳和DST值。

输出现在如下:

2015-03-01 19:07:17 1425222437 0
2015-03-01 11:07:17 1425226037 0
2015-03-01 20:07:17 1425226037 0

如您所见,两个创建的DateTime对象之间的unix时间戳已经不同。

现在我将具体时间指定为

$startDate = DateTime::createFromFormat('Y-n-d H:i', "$year-$month-01 00:00", $tzMoscow);

以及

$startDate = DateTime::createFromFormat('Y-n-d H:i', "$year-$month-01 00:00", $tzNewYork);

输出变为:

2015-03-01 00:00:00 1425153600 0
2015-03-01 00:00:00 1425186000 0
2015-03-01 09:00:00 1425186000 0

另一方面,如果我将$month更改为4(纽约使用DST),我会得到以下输出:

2015-04-01 19:08:35 1427900915 0
2015-04-01 11:08:35 1427900915 1
2015-04-01 19:08:35 1427900915 0

这些结果意味着什么?

纽约和莫斯科时区之间的转换在所有情况下都是正确的,因为您可以从unix时间戳相同来判断。此外,&#34; 2015-03-01 00:00和#34;莫斯科和纽约的时间戳明显不同,因为它们取决于具体的时区。

所以我认为你的代码是正确的,并且php中没有错误。然而,&#34;当前&#34;由于在3月1日至今天(3月14日)之间进行DST切换,纽约和莫斯科的时间有所不同。

虽然Jon的回答已经解释了这个理论(我不想要所有的功劳,但他是第一个),也许有人仍会找到一些有用的具体例子。

答案 2 :(得分:-1)

您可以使用此功能,在时区之间进行更改

function changeTimezone($time, $currentTimezone, $timezoneRequired, $FormtsTime = 'Y-m-d h:i:s')
{
    $dayLightFlag = false;
    $dayLgtSecCurrent = $dayLgtSecReq = 0;

    $system_timezone = date_default_timezone_get();
    $local_timezone = $currentTimezone;
    date_default_timezone_set($local_timezone);
    $local = date($FormtsTime);
    date_default_timezone_set("GMT");
    $gmt = date($FormtsTime);
    $require_timezone = $timezoneRequired;
    date_default_timezone_set($require_timezone);
    $required = date($FormtsTime);
    date_default_timezone_set($system_timezone);

    $diff1 = (strtotime($gmt) - strtotime($local));
    $diff2 = (strtotime($required) - strtotime($gmt));
    $date = new DateTime($time);
    $date->modify("+$diff1 seconds");
    $date->modify("+$diff2 seconds");

    if ($dayLightFlag) {
        $final_diff = $dayLgtSecCurrent + $dayLgtSecReq;
        $date->modify("$final_diff seconds");
    }

    $timestamp = $date->format($FormtsTime);

    return $timestamp;
}