DateTime::diff 奇怪的结果

DateTime::diff weired result

我用DateTime::diff来比较两个DateTime,结果很奇怪好像abs($date1 - $date2) != abs($date2 - $date1).

$date1 = new DateTime("1980-11-21 00:00:00");
$date2 = new DateTime("1981-11-20 00:00:00");
var_dump($date1->diff($date2,true)->days);
var_dump($date2->diff($date1,true)->days);
var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s"));
var_dump($date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));

哪个returns:

int(364)
int(364)
string(15) "00-11-30 00:0:0"
string(15) "00-11-29 00:0:0"

Demo

为什么不从最大值中减去最小值?
伪代码:

$diff = max($date1, $date2) - min($date1, $date2)

这样你应该总是得到相同和正确的结果。

好的,所以只是将我的评论作为答案。我的猜测是这是预期的行为,因为它是不同的天数,具体取决于您是向前还是向后。想象一下,从昨天到今天,一年多了,那是 366 天,因为你必须舍入 whole year plus 1 day。而从今天到昨天(去年)也只有 364 天,同理,是 whole year minus one day。至于解决方案,@Andreas 建议的选项是这里的方法。

结果似乎有线,但却是正确的: 解释为有些月份有 30 或 31(或 28)天。如果您要在 10 月执行此示例

    $date1 = new DateTime("1980-10-21 00:00:00");
    $date2 = new DateTime("1981-10-20 00:00:00");
    var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s"));
    var_dump($date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));
    var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s") == $date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));
string(15) "00-11-29 00:0:0"
string(15) "00-11-30 00:0:0"
bool(false)

或二月

string(15) "00-11-30 00:0:0"
string(15) "00-11-28 00:0:0"
bool(false)

还有

var_dump($date1->diff($date2,true)->format("%a"));

将始终显示

string(3) "365"

行为正确。两个日期间隔代表相同的天数 (364)。月份和日期部分表示从第一个日期到第二个日期需要相加to/subtracted的时间段:

1981-11-20 minus 1980-11-21 represents an interval of 11 month 30 day
1980-11-21 + 11 month = 1981-10-21
1981-10-21 + 30 day   = 1981-10-21

1980-11-21 minus 1981-11-20 represents an interval of 11 month 29 day
1981-11-20 - 11 month = 1980-12-20
1980-12-20 - 29 day   = 1980-11-21

一个更简单的例子是 10 月 21 日 ... 12 月 20 日:

  • 您需要将 10 月 21 日加上 1 个月 29 天才能到达 12 月 20 日(请注意,12 月之前的月份有 30 天)
  • 但是...您需要从 12 月 20 日减去 1 个月 30 天才能得到 10 月 21 日。Oct 本身有 31 天,这就解释了差异。