【问题标题】:DateTime::diff weired resultDateTime::diff 奇怪的结果
【发布时间】:2019-11-20 12:09:08
【问题描述】:

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

返回:

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

Demo

【问题讨论】:

  • 因为没有第0天(只有-1和1)?猜猜
  • @l00k 这也是我的猜测
  • 但是你为什么期望它是平等的呢?如果您及时前进或后退,那将是不同的天数。想象一下从昨天到今天(一年多),那将是 366 天,因为您必须整整一年 + 1 天。而且从今天到昨天只有 364 天,出于同样的原因,就是一整年减去一天。
  • 对不起,我对你的评论一无所知:D

标签: php datetime datediff dateinterval


【解决方案1】:

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

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 日。10 月本身有 31 天,这说明了差异。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      结果似乎是连贯的,但却是正确的: 可以用某些月份有 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"
      

      【讨论】:

      • 其实日子是一样的。你可以通过$diff->format("%a");查看它
      【解决方案4】:

      好的,只是将我的评论作为答案。我的猜测是这是预期的行为,因为它是不同的天数,具体取决于您是否及时前进或后退。想象一下从昨天到今天超过一年,那将是 366 天,因为您必须对 whole year plus 1 day 进行四舍五入。出于同样的原因,从今天到昨天(去年)只有 364 天,它是 whole year minus one day。至于解决方案,@Andreas 建议的选项就是这里的方法。

      【讨论】:

      • 我相信你应该再添加“去年”。您的回答说从今天到昨天是 364 天,这是不正确的。那是1。
      • 不,不是。它仍然是 AB,BA。
      • @Kris Roofe 为什么会这样?对不起,我不明白。今天和昨天是相邻的日子,就像您的问题中的 21/11 和 20/11 一样。
      • @KrisRoofe 我相信我做到了
      • @KrisRoofe 这确实有点奇怪。你可以使用->days 来达到你的目的吗?看起来天拥有“绝对”值,其他字段取决于“方向”
      猜你喜欢
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-07
      • 2016-11-28
      • 2012-12-16
      • 2012-12-06
      相关资源
      最近更新 更多