PHP DateTime sub 产生意外结果

PHP DateTime sub produces unexpected results

我有以下从 DateTimeImmutable 中减去 DateInterval 的示例

    $dateA = new DateTimeImmutable('2016-06-30');
    $dateB = new DateTimeImmutable('2016-05-31');
    $dateInterval = new DateInterval('P3M');
    // print 2016-03-30 as expected
    echo $dateA->sub($dateInterval)->format('Y-m-d'); 
    // print 2016-03-02 which i would expect 2016-02-29
    echo $dateB->sub($dateInterval)->format('Y-m-d');

当我将周期设置为 'P8M' 时,它按预期工作。怎么来的,二月份有效吗?

好的,这真的很简单(有点)。每个 'month' 间隔计算为前一个(或前 X 个)月的等效日。如果当月的天数多于登陆月的天数,超出的部分会溢出到下个月。

因此,如果您的日期是 2016 年 5 月 31 日,并且想要减去 3 个月的时间间隔,它将:

  • 返回 3 个月(在月份列表中,还没有考虑天数),导致 'February'
  • 然后寻找 2 月 31 日。这不存在,所以流血到下个月 2 天(2016 年 2 月有 29 天,所以多了 2 天)
  • 中提琴! 3 月 2 日。

继续,假设您在 2016 年 5 月 31 日,并且想增加一个月

  • 前进一个月到六月。
  • 寻找 6 月 31 日,不,多了 1 天,流血到 7 月。
  • 不出所料,7 月 1 日就是答案。

这方面的教训:添加和减去月份间隔很糟糕,令人困惑,并且可能导致非直观的结果,除非你有你的月份计算罗塞塔石碑。

来自PHP Docs

的解释

Note: Relative month values are calculated based on the length of months that they pass through. An example would be "+2 month 2011-11-30", which would produce "2012-01-30". This is due to November being 30 days in length, and December being 31 days in length, producing a total of 61 days.