【问题标题】:PHP DateTime objects not equal with modified TimezonePHP DateTime 对象与修改后的时区不相等
【发布时间】:2017-03-23 13:51:52
【问题描述】:

从 PHP 5.2.2 开始,支持使用比较运算符比较 DateTime 对象。

5.2.2 DateTime 对象与比较运算符的比较更改为按预期工作。以前,所有 DateTime 对象都被认为是相等的(使用 ==)。

我的问题是,当我修改现有 DateTime 对象的时区时,它不再等于更改时区之前等于的 DateTime 对象。更奇怪的是,如果我在修改后的 DateTime 对象上调用 DateTime::getTimestamp(),它现在将等于另一个 DateTime 对象。

例如:

<?php

$dt = new DateTime("2016-11-08 08:27:33am -08");
$dt2 = new DateTime("2016-11-08 09:27:33am -07");

var_dump($dt == $dt2);

$dt2->setTimezone(new DateTimeZone("-08"));

var_dump($dt == $dt2);
var_dump($dt < $dt2);
var_dump($dt > $dt2);

var_dump($dt2->getTimestamp());

var_dump($dt == $dt2);
var_dump($dt < $dt2);
var_dump($dt > $dt2);

将产生以下输出:

bool(true)

bool(false)
bool(false)
bool(true)

int(1478622453)

bool(true)
bool(false)
bool(false)

那是什么?如您所见,$dt$dt2 在创建时是相等的,尽管它们位于不同的时区。不过,这种行为是意料之中的。 $dt$dt2 都代表完全相同的时刻。如果您同时拨打getTimestamp(),您将获得相同的号码。同样,如果您明确设置两个 DateTime 的时区,它们将相等。

PHP 手册确实指出,如果初始化字符串包含时区(或者是 unix 时间戳),则忽略时区:

注意: 当 $time 参数是 UNIX 时间戳(例如 @946684800)或指定时区(例如 2010-01-28T15:00:00+02:00)时,$timezone 参数和当前时区将被忽略。

所以我确实相信这是导致这种看似不正常的行为的原因,但我不介意知道原因。

那么,有人知道为什么 DateTimes 会这样吗? DateTime 对象实际上是如何比较的?如果您仍需要将 DateTime 对象与另一个 DateTime 对象进行比较,那么更改其时区的最佳方法是什么?

【问题讨论】:

  • 更令人毛骨悚然:-S pastebin.com/b8VXm5dG
  • 对我来说看起来像一个错误。报告它。请注意,-08 不是真正的时区。如果您使用实时时区,也许您可​​以获得更好的结果。
  • 虽然偏移量确实不是实时时区,但 PHP 的文档没有出现来表明它是否支持偏移量。如果我可以在这个实现中使用确切的时区,我会的。不幸的是,在这种情况下这是不可能的。像这样的代码:&lt;?php $dt = DateTime::createFromFormat('O', "-08"); var_export($dt); 将时区显示为“-08:00”。

标签: php datetime


【解决方案1】:

那是php bug。要解决此问题,您可以扩展 DateTime 类并覆盖 setTimezone 方法,如下所示:

    class MyDateTime extends DateTime {
        public function setTimezone($timezone) {
            parent::setTimezone($timezone);
            $this->getTimestamp();
            return $this;
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 2020-11-21
    相关资源
    最近更新 更多