如何在PHP的DateTime中为Leap Seconds启用完整的UTC支持?

时间:2013-01-08 02:32:13

标签: php datetime leap-second

我想用Leap Seconds进行一些DateTime计算,但它很早就停止了,因为我无法告诉DateTime我的意思:

### June 30, 2012 at 23:59:60 UTC ###

$leap = new DateTime('2012-06-30T23:59:60UTC');
var_export($leap);

输出:

DateTime::__set_state(array(
   'date' => '2012-07-01 00:00:00',
   'timezone_type' => 3,
   'timezone' => 'UTC',
))

我无法为去年的UTC闰秒创建DateTime(也不是我尝试过的其他闰秒)。我想知道DateTime是否支持闰秒,我认为它支持UTC,但可能不支持闰秒,所以只支持GMT?

2 个答案:

答案 0 :(得分:2)

UNIX时间不知道闰秒。就其而言,每天恰好包含86,400秒,并且恰好偶尔跳过或重复一秒钟。 (这在很大程度上是必要的,因为闰秒没有提前完全安排。如果在UNIX时间内计算闰秒,则UNIX时间与人类可读日期/时间之间的“映射”将随着闰秒的宣布而不可预测地改变。)

由于其日期/时间原语都基于UNIX时间,因此PHP也不能轻易表示闰秒。它们实际上是不可见的。

答案 1 :(得分:1)

这不是一个很好的答案,但至少它是什么。

这里有两个可能的问题:

  1. 正如ircmaxell所提到的,PHP可能会在时区操作位中的某个地方吃掉闰秒,但还需要更多的研究。
  2. 但是我个人希望PHP将“秒”的“溢出”修复为分钟。 DateTime构造函数通过处理strtotime的相同代码传递给定参数,这是众所周知的完全虚假日期(例如2月31日)并将它们转换为某种可能的类型感。
  3. 文档中对闰秒的唯一引用是strptime

      

    “tm_sec”包括任何闰秒(目前最多2年)。

    例如,从PHP交互式提示符缩写:

    php > $eviler_format = '%Y-%m-%d %H:%M:%S %z';
    php > $evil = '2012-12-31 23:59:59 +0000';
    php > var_dump(strptime($evil, $eviler_format));
    array(9) {
      'tm_sec' =>
      int(59) // ...
    }
    php > $evil = '2012-12-31 23:59:60 +0000';
    php > var_dump(strptime($evil, $eviler_format));
    array(9) {
      'tm_sec' =>
      int(60) // ...
    }
    php > $evil = '2012-12-31 23:59:61 +0000';
    php > var_dump(strptime($evil, $eviler_format));
    array(9) {
      'tm_sec' =>
      int(61) // ...
    }
    php > $evil = '2012-12-31 23:59:62 +0000';
    php > var_dump(strptime($evil, $eviler_format));
    bool(false)
    

    不幸的是,它还需要12月31日的“闰秒”:

    php > $evil = '2012-01-07 23:59:61 +0000';
    php > var_dump(strptime($evil, $eviler_format));
    array(9) {
      'tm_sec' =>
      int(61)
      'tm_min' =>
      int(59)
      'tm_hour' =>
      int(23)
      'tm_mday' =>
      int(7)
      'tm_mon' =>
      int(0)
      'tm_year' =>
      int(112)
      'tm_wday' =>
      int(6)
      'tm_yday' =>
      int(6)
      'unparsed' =>
      string(0) ""
    }
    

    或者不是午夜:

    php > $evil = '2012-01-07 08:59:61 +0000';
    php > var_dump(strptime($evil, $eviler_format));
    array(9) {
      'tm_sec' =>
      int(61)
      'tm_min' =>
      int(59)
      'tm_hour' =>
      int(8)
      'tm_mday' =>
      int(7)
      'tm_mon' =>
      int(0)
      'tm_year' =>
      int(112)
      'tm_wday' =>
      int(6)
      'tm_yday' =>
      int(6)
      'unparsed' =>
      string(0) ""
    }
    

    此外,它完全是一个表示功能,不以任何方式附加到DateTime。你不能对它进行数学运算,并且在现实生活中实现真正闰秒是不可能的,因为事物的定义很明确。这里没用。

    结论:PHP没有考虑闰秒。确保您的服务器与 关心它的上游NTP服务器同步,您最终会没事的。如果您需要关注闰秒的二级精度,那么PHP可能是您错误的语言。