【问题标题】:PHP DateTime does not correctly calculate time component when adding across DST boundaries跨 DST 边界添加时,PHP DateTime 无法正确计算时间分量
【发布时间】:2020-03-07 14:27:42
【问题描述】:

考虑下面的代码

$participantTriggerDate = new \DateTime('2019-06-14 09:40:00.000000', new DateTimeZone('US/Central'));
$dateInterval = new \DateInterval('P150D');

$newDate = \DateTimeImmutable::createFromMutable($participantTriggerDate);
$newDate = $newDate->add($dateInterval);

echo(json_encode([
    'participantTriggerDate' => $participantTriggerDate,
    'newDate' => $newDate,
]));

此代码产生以下输出:

{
  "participantTriggerDate": {
    "date": "2019-06-14 09:40:00.000000",
    "timezone_type": 3,
    "timezone": "US/Central"
  },
  "newDate": {
    "date": "2019-11-11 09:40:00.000000",
    "timezone_type": 3,
    "timezone": "US/Central"
  }
}

但是,由于 2019-06-14 过去 150 天跨越了 DST 边界,PHP 不应该从时间中减去和小时吗?我认为 PHP 在后台处理了所有凌乱的 DST 内容。有没有办法让我正确计算这个时间?从我读到的内容看来,推荐的答案是将所有内容都转换为 UTC 并在那里进行计算。如果可能的话,我想避免这种情况。我认为 PHP 足够聪明,可以知道当我将时区传递给 DateTime 创建时,跨越了 DST 边界。

【问题讨论】:

  • DateInterval() 会针对 DST 进行调整,因此如果您说它应该是 0H,那么它将是一天中的同一时间,而与 DST 无关。
  • 这通常是人们想要的。当你说你想在 N 天后做某事时,意思是在一天中的同一时间。
  • @Barmar 我认为通过不指定时间组件,PHP 会知道将 150 天添加到日期会导致跨越 DST 边界,并会适当地调整时间。情况似乎并非如此。是否需要在 DateInterval 字符串中添加一些内容才能让 PHP 正确计算时间分量?在这个当前的形式中,很明显 PHP 的 DateInterval 在添加到日期时没有正确计算 DST 更改。
  • 为什么说不调整?两个日期的时间都是09:40
  • 关键是它会自动调整,因此您不会注意到额外或缺失的时间。 150 天不等于 150*24 小时。

标签: php datetime time timezone timezone-offset


【解决方案1】:

当您添加一整天时,PHP 会生成相同的一天中的时间,即使 DST 已更改。如果要添加时间间隔而不进行此调整,则需要添加小时而不是天。将天数乘以 24 即可得到。

$dateInterval = new \DateInterval('PT3600H'); // 3600 = 150*24

【讨论】:

    猜你喜欢
    • 2017-06-29
    • 1970-01-01
    • 2021-03-13
    • 2014-04-17
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多