【问题标题】:Comparing DateTime PHP in daylight saving time在夏令时比较 DateTime PHP
【发布时间】:2021-12-24 02:27:04
【问题描述】:

我想知道是否有办法在 DateTime 中处理夏令时比较

$timezone = "America/New_York";

$date1 = new DateTime('2021-11-07 01:55:00.000000', new DateTimeZone($timezone));
$date1->add(new DateInterval("PT5M"));
$date2 = new DateTime('2021-11-07 01:55:00.000000', new DateTimeZone($timezone));

/*
$date1 = 2021-11-07 01:00:00.000000
$date2 = 2021-11-07 01:55:00.000000
*/
var_dump($date1 > $date2);
/*
result: bool(true)
*/

【问题讨论】:

  • 可能使用或转换为不遵守夏令时的 UTC
  • 在 UTC 中进行所有存储和数学运算并将结果转换为本地时间可以解决许多与 DST 相关的问题(包括一些 PHP 错误),但这并不总是可行的(有时是本地时间需要作为起点)。

标签: php date datetime compare


【解决方案1】:

众所周知,DST 切换会引入重复的本地时间。如果您在 2:00 将时钟向后移动 1 小时,那么您将在同一天两次获得 1:00。 PHP 能够处理它并跟踪它是哪个 1:00。最好用另一个测试用例来说明这一点:

$timeZone = new DateTimeZone('America/New_York');

$modified = new DateTime('2021-11-07 01:55:00.000000', $timeZone);
$modified->add(new DateInterval('PT5M'));
$raw = new DateTime('2021-11-07 01:00:00.000000', $timeZone);
var_dump($modified, $raw, $modified == $raw, $modified < $raw, $modified > $raw);

$control = new DateTime('2021-11-07 01:00:00.000000', $timeZone);
var_dump($raw, $raw, $control == $raw, $control < $raw, $control > $raw);
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2021-11-07 01:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "America/New_York"
}
object(DateTime)#3 (3) {
  ["date"]=>
  string(26) "2021-11-07 01:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "America/New_York"
}
bool(false)
bool(false)
bool(true)
object(DateTime)#3 (3) {
  ["date"]=>
  string(26) "2021-11-07 01:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "America/New_York"
}
object(DateTime)#3 (3) {
  ["date"]=>
  string(26) "2021-11-07 01:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "America/New_York"
}
bool(true)
bool(false)
bool(false)

如果我们设置1:55 并继续前进,PHP 知道结果时间是第二个1:00。如果我们直接设置1:00,它假定它是第一个1:00——老实说,它没有办法知道你指的是哪个,因为地理时区标识符会造成这种歧义。即使var_dump() 也无法显示差异。

另一方面,这些重复的1:00s 并不真正模棱两可,因为它们属于不同的时区:EDTEST。就是这样:

var_dump($modified->format('r T'), $raw->format('r T'), $control->format('r T'));
string(35) "Sun, 07 Nov 2021 01:00:00 -0500 EST"
string(35) "Sun, 07 Nov 2021 01:00:00 -0400 EDT"
string(35) "Sun, 07 Nov 2021 01:00:00 -0400 EDT"

简而言之,这里的一切都按预期工作。唯一的潜在问题是当您需要在 DST 边界处精确设置时间时,因为由于地理标识符的模糊性而无法使用它。您需要指定ESTEDT,这不太方便,也不一定是等效的。

【讨论】:

  • 非常感谢您的完整回答,我真的需要在 DST 设置一个时间,所以我可能需要指定 EST 或 EDT
猜你喜欢
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 2018-03-14
  • 1970-01-01
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 2015-04-09
相关资源
最近更新 更多