使用DateInterval和DateTime::add添加月份时会出现什么问题


What can go wrong when adding months with a DateInterval and DateTime::add?

我未能找到解决此问题的正确方法。正如您在PHP文档中的示例#3中所看到的,它们指出在使用DateTime::add中的DateInterval添加月份时必须小心。

对于为什么这个方法的行为是这样的,以及我能做些什么来避免这种情况,我没有任何真正的解释,我一看就是一个错误。

有人对此有所了解吗?

问题是每个月可能有不同的天数。问题是,当你想将日期增加1个月时,你在做什么。根据PHP文档,如果您在1月31日(或30日),并且添加了1个月,那么预期的行为是什么?

二月只有29天。你想定在一个月的最后一天吗?如果你想要的是一个固定的天数,或者是一个基于当前日期的静态日期,那么你通常会更安全。如果不知道当你增加一个月的时间时你想完成什么,很难说如何注意错误。

编辑:
正如有人在上面Mike B评论的类似帖子中提到的那样,你可能想做一些事情(在伪代码中):

 1) Use cal_days_in_month() for the next month and save that number to a variable x
 2) If x >= current billing DOB, increment and be done
 3) DateTime::modify('last day')  (havent used this before but something along these lines) to set the date to the last date of the next month (set it to the 1st of the next month, then last day?)

值得注意的是,如果您使用此处的变量作为新的计费值,您将删除您的原始值。我会保存一个额外的DB值,它是"第一个计费日期"或只是"billing_day_of_month"之类的,并用它来计算出你应该查看的月份

如果您的目标是严格增加用户友好的月份(因此,从1月21日起的3个月应该是4月21日),除了较短的会员月份会缩短(因此,1月31日起的1个月是2月28/29日),那么如果您进入下一个月,您只需要返回几天:

function addMonths($date,$months) {
  $orig_day = $date->format("d");
  $date->modify("+".$months." months");
  while ($date->format("d")<$orig_day && $date->format("d")<5)
    $date->modify("-1 day");
}
$d = new DateTime("2000-01-31");
addMonths($d,1);
echo $d->format("Y-m-d"); // 2000-02-29