2012-02-14 40 views
4

我未能找到解决此问题的适当解决方案。正如您在PHP文档中的Example#3中看到的,他们声明one must beware when adding months在DateTime :: add中使用DateInterval。使用DateInterval和DateTime :: add添加月份时会出现什么问题?

对于为什么这种方法的行为是这样的,我可以做些什么来避免这种情况,我发现这是一见钟情。

有人对此有所了解吗?

+0

可能非常相似,http://stackoverflow.com/questions/7119777/php-strotime-1-month-behaviour – 2012-02-14 18:42:01

+0

*(refe rence)* http://www.gnu.org/software/tar/manual/html_node/Relative-items-in-date-strings.html#SEC120 – Gordon 2012-02-14 18:54:29

+1

@MikeB它与strtotime不同,因为它是一个新的实现。我一直在寻找一种等于strtotime给我的解决方案,但更聪明。 OO DateTime类将是可取的。 – 2012-02-14 21:43:38

回答

7

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

2月份只有29天。你想设置到月的最后一天吗?如果这是您正在寻找的内容,或者基于当前日期的静态日期,您通常会更安全地递增一定的天数。当你增加月份时,不知道你想要完成什么,很难说如何看错误。

编辑:
正如有人在通过上述迈克乙评论了类似的帖子中提到,你可能想要做的事,你(在伪代码):

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”或其他内容,并用它来计算出您应该查看的月份日期

+0

你知道,这非常明显。我想实现的目标是我的客户每月支付一次,因此我需要将其订阅到期日期增加1个月。然而,这显然是一个糟糕的实现和客户混淆,因此我需要找出另一个解决方案。 – 2012-02-14 21:47:31

+1

我想这里有很多悖论。我提出的解决方案是,如果用户在任何月份的29日,30日或31日报名,他们将收到3天,2天或1天的费用,他们的订购日将设置为每月28日。我选择这种解决方案,而不是将每个客户的计费日设置为1日,因为处理付款的服务器不应该每个月只有一天繁忙。 – 2012-02-15 17:28:48

+0

最好是增加30天而不是乱用几个月?我们可以避免这种情况。 – CMCDragonkai 2013-12-02 05:05:34

0

如果您的目标是严格按用户增加友好的月份(因此,从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 
相关问题