Add 1 month to January (1-28th), 2011, should produce February (1-28th), 2011.
Add 1 month to January 30th, 2011, should produce February 28th, 2011.
Add 3 months to January 31st, 2011, should produce April 30th, 2011.
Add 13 months to January 30th, 2011, should produce February 29th, 2012.
Add 1 month to October 31st, 2011, should produce November 30th, 2011.
如果我在 PHP 中使用日期加法,则会出现溢出:
Adding 1 month to January 30th, 2011, results in March 2nd, 2011.
function add($date_str, $months)
{
$date = new DateTime($date_str);
// We extract the day of the month as $start_day
$start_day = $date->format('j');
// We add 1 month to the given date
$date->modify("+{$months} month");
// We extract the day of the month again so we can compare
$end_day = $date->format('j');
if ($start_day != $end_day)
{
// The day of the month isn't the same anymore, so we correct the date
$date->modify('last day of last month');
}
return $date;
}
$result = add('2011-01-28', 1); // 2011-02-28
$result = add('2011-01-31', 3); // 2011-04-30
$result = add('2011-01-30', 13); // 2012-02-29
$result = add('2011-10-31', 1); // 2011-11-30
$result = add('2011-12-30', 1); // 2011-02-28
<?php
$date = "2011-01-30";
list($year,$month,$day) = explode("-",$date);
// add month here
$month++;
// to avoid a month-wrap, set the day to the number of days of the new month if it's too high
$day = min($day,date("t",strtotime($year."-".$month."-01")));
$date = $year."-".$month."-".$day;
// 2011-02-28
echo $date;
?>
//Create the date, store its day-of-month, and add X months
$myDateTimeISO = "2012-01-31";
$addThese = 1;
$myDateTime = new DateTime($myDateTimeISO);
$myDayOfMonth = date_format($myDateTime,'j');
date_modify($myDateTime,"+$addThese months");
//Find out if the day-of-month has dropped
$myNewDayOfMonth = date_format($myDateTime,'j');
if ($myDayOfMonth > 28 && $myNewDayOfMonth < 4){
//If so, fix by going back the number of days that have spilled over
date_modify($myDateTime,"-$myNewDayOfMonth days");
}
echo date_format($myDateTime,"Y-m-d");
结果是:2012-02-29(是的,这是闰年)。
PS:如果您想添加年份,问题和症状几乎相同。同样,您只需要检查结果中的日期是否为 1/2/3,而输入的日期是否为 29/30/31。如果是这样,您需要使用 date_modify 返回 \'-X 天\',其中 X 是结果中的日期。
/**
* @var \DateInterval
*/
private $remainder;
/**
* @param \DateTimeImmutable $date
* @param string $modifier
* @return \DateTimeImmutable
*/
private function nextInterval(\DateTimeImmutable $date, $modifier)
{
$dayNumber = (int)$date->format('j');
$next = $date->modify($modifier);
if (!is_null($this->remainder)) {
$next = $next->add($this->remainder);
$dayNumber += $this->remainder->days;
$this->remainder = null;
}
// This should in general only apply to months which do not have the same daynumber in that month after adding
if ($dayNumber !== (int)$next->format('j')) {
$n = $next->modify('last day of last month');
$this->remainder = $n->diff($next);
$next = $n;
}
return $next;
}
function addMonthGetLastDate($date_str, $months)
{
list($year,$month,$day) = explode("-",$date_str);
// add month here
$month += ($months-1);
if($month>12)
{
$month = $month - 12;
$year += 1;
}
// to avoid a month-wrap, set the day to the number of days of the new month if it's too high
$day = min($day,date("t",strtotime($year."-".$month.".01.")));
$date = date('Y-m-t', strtotime($year."-".$month."-".$day));
return $date;
}