PHP和DST转换问题

I'm having trouble understanding how my code adapts to DST, as it's incorrect with the recent update. I'm storing a date time in the database based on UTC and then converting it back to the local timezone for display. If PHP is taking DST into account, something else is wrong because all of my stored dates are 1 hour off.

$stored_date = '2016-11-16 12:04:01'; // in UTC

$dateTime = new DateTime($stored_date, new DateTimeZone('UTC'));
$dateTimeZone = new DateTimeZone('America/New_York');
$dateTime->setTimezone($dateTimeZone);

print_r($dateTime);

Last week, before DST ended, this would have printed out 2016-11-16 08:04:01. This week, now that DST has ended, it prints out 2016-11-16 07:04:01. Why the hour difference if PHP is properly handing the DST shift?

It shouldn't matter the server settings (I don't think) because I'm explicitly doing the conversion within PHP, right?

I'm ready to start doing a check with PHP to see if DST is in effect and offsetting the conversion by 1 hour because I can't figure out why that hour isn't being automatically compensated for within the DateTime class.

dongyuhui0418
dongyuhui0418 我们在11月“退回”,所以在时间变化之前的08:04:01应该是07:04:01之后。美洲/纽约从-4变为-5。我觉得这里没问题。
3 年多之前 回复
douyanqu9722
douyanqu9722 知道了,这很有道理。
3 年多之前 回复
dr2898
dr2898 那个日期是在DST改变之后所以它永远不应该是2016-11-1608:04:01。DST更改前的日期应为08:04:01但不是之后。
3 年多之前 回复
douqin1932
douqin1932 无论DST是否生效,结果应该是2016-11-1608:04:01。我假设当PHP从UTC转换到另一个时区时,它会知道DST是否生效并产生相同的本地时间。也许答案是PHP在技术上做得对,我需要通过调整DST来弥补我的业务案例。
3 年多之前 回复
dpoh61610
dpoh61610 小时差是否代表DST的变化,这是您所期望的?我不确定你期望与众不同。
3 年多之前 回复

1个回答

New York city switches between these time zones:

  • Winter: EST (Eastern Standard Time) = UTC -5
  • Summer: EDT (Eastern Daylight Time) = UTC -4

According to timeanddate.com the switch will happen on 6th of November. Thus the result is correct: 12 - 5 = 7

In other words, PHP is perfectly aware of DST, as we can see in the following code:

$dateTime = new DateTime('2016-11-05 12:04:01', new DateTimeZone('UTC'));
$dateTime->setTimezone(new DateTimeZone('America/New_York'));
echo $dateTime->format('r') . PHP_EOL;

$dateTime = new DateTime('2016-11-06 12:04:01', new DateTimeZone('UTC'));
$dateTime->setTimezone(new DateTimeZone('America/New_York'));
echo $dateTime->format('r') . PHP_EOL;
Sat, 05 Nov 2016 08:04:01 -0400
Sun, 06 Nov 2016 07:04:01 -0500

You can inspect the exact information available in your system's time database:

$timeZone = new DateTimeZone('America/New_York');
print_r($timeZone->getTransitions(mktime(0, 0, 0, 1, 1, 2016), mktime(0, 0, 0, 12, 31, 2016)));
Array
(
    [0] => Array
        (
            [ts] => 1451602800
            [time] => 2015-12-31T23:00:00+0000
            [offset] => -18000
            [isdst] => 
            [abbr] => EST
        )

    [1] => Array
        (
            [ts] => 1457852400
            [time] => 2016-03-13T07:00:00+0000
            [offset] => -14400
            [isdst] => 1
            [abbr] => EDT
        )

    [2] => Array
        (
            [ts] => 1478412000
            [time] => 2016-11-06T06:00:00+0000
            [offset] => -18000
            [isdst] => 
            [abbr] => EST
        )

)
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问