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

时间:2019-03-01 20:33:32

标签: php date datetime time timezone

我有四个日期不同的日期,但相同时间

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的日期显示为不同的时间。 answer 是因为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

2 个答案:

答案 0 :(得分:2)

  

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

对不起,但是这种思路是有问题的。对于美国太平洋时区(由America/Los_Angeles表示)的人们来说,夏令时不是不可选择的。他们没有选择加入还是退出的选择。

如果您要处理一些明确的业务要求,例如“不必担心DST”,那么,抱歉,但是您应该继续这样做。否则,您的代码将在一年中的大部分时间内生成不正确的结果。 (在美国,白天实际上比标准时间更长!)

但是,如果您真正想得到的不是美国太平洋时区的时间,而是UTC-8固定偏移量的时间,那么请使用时区{{1,而不是America/Los_Angeles }}(请注意,符号是故意反转的)。无论您一年中的什么时间,都将使用UTC-8。

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

Refer to the full list of time zones here.

就您提出的关于Pacific/Pitcairn20:00:00 UTC但为12:00:00 PST的观点来看,的确是事实。如果要一个接一个地跟踪24小时,则无法避免这一事实。即使您每天都跟踪“太平洋时间中午”,您在转换前后也会得到不同的对应UTC时间。

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

如果您认为 很复杂,请考虑并非每个时区都有1小时DST增量。澳大利亚(13:00:00 PDT)的豪勋爵岛有30分钟的路程。在标准时间为UTC + 10:30,在白天为UTC + 11。

答案 1 :(得分: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,它指的是格林尼治标准时间早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