DateTime :: diff意外结果

时间:2018-01-25 03:29:58

标签: php datetime dateinterval

我有以下计算,我希望返回0.但是在我有权访问的许多系统上它返回1:

Ubuntu 16.04服务器(错误)

php -v
PHP 7.0.22-0ubuntu0.16.04.1 (cli) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.22-0ubuntu0.16.04.1, Copyright (c) 1999-
2017, by Zend Technologies

echo "<?php echo DateTime::createFromFormat('Y-m-d H:i:s', '2017-12-01 00:00:00')->diff(DateTime::createFromFormat('Y-m-d H:i:s', '2017-12-31 23:59:59' ))->format('%m');"|php
1

来自deb.sury.org的PHP 7.1与Xdebug(错误)

php -v
PHP 7.1.6-1~ubuntu16.04.1+deb.sury.org+1 (cli) (built: Jun  9 2017 
08:26:34) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.1.6-1~ubuntu16.04.1+deb.sury.org+1, Copyright 
(c) 1999-2017, by Zend Technologies
    with Xdebug v2.5.4, Copyright (c) 2002-2017, by Derick Rethans

echo "<?php echo DateTime::createFromFormat('Y-m-d H:i:s', '2017-12-01 00:00:00')->diff(DateTime::createFromFormat('Y-m-d H:i:s', '2017-12-31 23:59:59' ))->format('%m');"|php
1

phpfiddle.org

- &GT;按预期返回0

日期的时区是相同的

1 个答案:

答案 0 :(得分:0)

来自DateInterval::format的说明:

  

DateInterval :: format()方法不会重新计算时间字符串中的结转点或日期段。这是预期的,因为不可能溢出像#32; 32天&#34;可以解释为&#34; 1个月和4天&#34;到&#34; 1个月和1天&#34;。

所以必须重新计算结转点数。以下是DateInterval::format的{​​{3}}:

class DateIntervalEnhanced extends DateInterval {
    public function recalculate() {
        $from = new DateTime;
        $to = clone $from;
        $to->add($this);
        $diff = $from->diff($to);
        foreach ($diff as $k => $v) $this->$k = $v;
        return $this;
    }
}

效用函数:

function myFormatter($d1, $d2, $format) {
    $diff = strtotime($d1) - strtotime($d2);
    $df = abs($diff);
    $di = new DateIntervalEnhanced("PT${df}S");
    $di->invert = $diff < 0;
    return $di->recalculate()->format($format);
}

echo myFormatter("2017-12-31 23:59:59", "2017-12-01 00:00:00", "%m");

<强> relevant code

<强> DEMO