DateTime::diff unexpected results

余生长醉 提交于 2020-01-03 04:21:48

问题


I have the following calculation, which I expect to return 0. However it returns 1 on many systems I have access to:

Ubuntu 16.04 server (wrong)

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

PHP 7.1 from deb.sury.org with Xdebug (wrong)

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

--> returns 0 as expected

The timezones of the date are the same


回答1:


A note from DateInterval::format:

The DateInterval::format() method does not recalculate carry over points in time strings nor in date segments. This is expected because it is not possible to overflow values like "32 days" which could be interpreted as anything from "1 month and 4 days" to "1 month and 1 day".

So one has to recalculate carry over points. Below is the relevant code from DateInterval::format:

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;
    }
}

A utility function:

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");

DEMO

Link to a post you might wanna read



来源:https://stackoverflow.com/questions/48435169/datetimediff-unexpected-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!