为什么日期和时间转换在不同日期有所不同?

问题描述 投票:1回答:2

我有四个日期,日期不同,但同一时间:

2019-03-02 20:00:00
2019-03-05 20:00:00
2019-03-10 20:00:00
2019-03-18 20:00:00

这些日期和时间以UTC格式。我想将它转换为时区,例如洛杉矶。

这是代码:

$dateTime = '2019-03-02 20:00:00';

$dt = new DateTime($dateTime, new DateTimeZone('UTC'));
$dt->setTimeZone(new DateTimeZone('America/Los_Angeles'));
$new = $dt->format('Y-m-d H:i:s');

echo $new;

2019-03-10和2019-03-18的日期显示为不同的时间。答案是因为在3月10日,由于节省了一天的光,它将提前1小时。

以下是它的结果:

2019-03-02 12:00:00
2019-03-05 12:00:00
2019-03-10 13:00:00
2019-03-18 13:00:00

我的问题是,如何使用上面的代码格式化我的日期,而不是节省日光。我只想转换我的时间,没有夏令时。我怎样才能做到这一点?这是我的预期输出:

2019-03-02 12:00:00
2019-03-05 12:00:00
2019-03-10 12:00:00
2019-03-18 12:00:00

他们都在12:00:00

php date datetime time timezone
2个回答
2
投票

我只想转换我的时间,没有夏令时。

对不起,但这种想法是有问题的。夏令时不是美国太平洋时区人民的选择(由America/Los_Angeles代表)。他们无法选择是选择加入还是选择退出。

如果您正在尝试处理某些明确的业务要求,例如“不要担心DST” - 抱歉,您应该继续推进。否则,您的代码将在一年中的大部分时间生成错误的结果。 (在美国,白昼时间实际上比标准时期长!)

但是,如果您真正追求的不是美国太平洋时区的时间,而只是UTC-8固定偏移的时间,那么请使用时区America/Los_Angeles而不是Etc/GMT+8(注意标志是故意倒置的) 。无论您在谈论什么时间,这都将使用UTC-8。

请记住,Etc/GMT*区域主要用于边缘情况,例如海上船舶的时间。如果您只想跟踪世界其他地方的时间,请为该位置选择适当的时区。例如,皮特凯恩群岛全年使用UTC-8并将其称为PST,其时区标识符为Pacific/Pitcairn

Refer to the full list of time zones here.

至于你对20:00:00 UTC12:00:00 PST13:00:00 PDT的观点 - 事实上这就是现实。如果你一个接一个地跟踪24小时的时间段,那么就没有办法避免这个事实。即使您每天跟踪“太平洋时间的中午”,您也会在转换前后获得不同的相应UTC时间。

虽然UTC时间是24小时,但是当我们在春季从PST切换到PDT时,美​​国太平洋时间的过渡天数是23小时,而在秋天我们从PDT切换到PST时,秋天则是25小时。

如果您认为这很复杂,请考虑并非每个时区都有1小时的DST增量。澳大利亚豪勋爵岛(Australia/Lord_Howe)有30分钟的三角洲。它们在标准时间内为UTC + 10:30,在白天时间为UTC + 11。


1
投票

由于PHP DateTime对象始终考虑夏令时,因此您需要通过减去夏令时无效时的时差来进行转换。这段代码应该做你想要的:

$utctime = new DateTime('2019-01-01', new DateTimeZone('UTC'));
$localtime = new DateTime('2019-01-01', new DateTimeZone('America/Los_Angeles'));
$diff = $localtime->diff($utctime);
foreach ($dates as $date) {
    $dt = new DateTime($date, new DateTimeZone('UTC'));
    $dt->add($diff);
    echo $dt->format('Y-m-d H:i:s');
}

输出:

2019-03-02 12:00:00
2019-03-05 12:00:00
2019-03-10 12:00:00
2019-03-18 12:00:00

Demo on 3v4l.org

更新

正如@MattJohnson指出的那样,存在一个时区Etc/GMT+8,它指的是比GMT提前8小时(无论夏令时如何)。您可以使用该时区来调整时间:

$west_coast = new DateTimeZone('Etc/GMT+8');
foreach ($dates as $date) {
    $dt = new DateTime($date, new DateTimeZone('UTC'));
    $dt->setTimeZone($west_coast);
    echo $dt->format('Y-m-d H:i:s') . "\n";
}

输出与上面相同。 Demo on 3v4l.org

© www.soinside.com 2019 - 2024. All rights reserved.