你说:-
如果您需要可靠和准确的日期操作,似乎无法使用strotime
你可以使用,只需了解它的行为方式。您的问题促使我运行了几个测试。
在减去一个月时,PHP并不仅仅是从日期中减去30天,尽管从你所看到的单个案例来看似乎是这样。实际上,我的测试here表明,在这种情况下,它会将31天添加到上个月的开始(3月3日的结果让我这样认为)。
$thirtyOnedayMonths = array(
1, 3, 5, 7, 8, 10, 12
);
$oneMonth = new \DateInterval('P1M');
$format = 'Y-m-d';
foreach($thirtyOnedayMonths as $month){
$date = new \DateTime("2013-{$month}-31 00:00:01");
var_dump($date->format($format));
$date->sub($oneMonth);
var_dump($date->format($format));
}
2013年11月12日和2013年10月12日之间相隔31天,PHP正确计算了月份减法,可以在这里看到。
$date = new \DateTime('2013-11-12 00:00:01');
var_dump($date);
$interval = new DateInterval('P1M');
$date->sub($interval);
var_dump($date);
在您的情况下,2013-10-31 - 1个月是2013-09-31,而这个日期并不存在。任何日期/时间函数都需要返回一个有效的日期,而2013-09-31不是有效日期。
在这种情况下,PHP似乎会在上个月的开始日期加上31天来得到一个有效日期。
一旦您知道了预期的行为,就可以相应地编写程序。如果当前的行为与您的用例不符,则可以扩展DateTime类以提供适合您的行为。
我假设strtotime和DateTime :: sub()的行为相同,但
this test表明它们确实如此。
$thirtyOnedayMonths = array(
1, 3, 5, 7, 8, 10, 12
);
$format = 'Y-m-d';
foreach($thirtyOnedayMonths as $month){
$date = date($format, strtotime('-1 month', strtotime("2013-{$month}-31 00:00:01")));
var_dump($date);
}