Как добавить 1 месяц на дату без пропусков, т.е. Февраль

Возможный дубликат:
PHP DateTime:: изменить время добавления и вычитания

У меня есть дата начала (т.е. 2011-01-30) и вы хотите добавить 1 месяц.

Проблема заключается в определении того, что такое месяц. Поэтому, если я использую следующий код:

$d1 = DateTime::createFromFormat('Y-m-d H:i:s', '2011-01-30 15:57:57');
$d1->add(new DateInterval('P1M'));
echo $d1->format('Y-m-d H:i:s');

Получаю следующий результат: 2011-03-02 15:57:57

Проблема заключается в том, что мне нужно, чтобы она использовала следующие правила:

  • Если я добавлю 1 месяц, он просто добавит 1 в месяц и оставит часть дня (2011-01-15 станет 2011-02-15)
  • Если день не будет в течение месяца, мы закончим, мы возьмем последний его день (2011-01-30 станет 2011-02-28)

Есть ли общая функция в php, которая может это сделать, или я должен сам ее кодировать? Может быть, я просто пропустил параметр или что-то в этом роде?

Ответ 1

Кажется, что для него нет готовой функции, поэтому я написал ее сам. Это должно решить мою проблему. В любом случае, спасибо за ваши ответы и комментарии. Если вы найдете некоторые ошибки, предоставьте в комментариях.

Эта функция вычисляет месяц и год, в которые я закончу, после добавления месяца. Затем он проверяет правильность даты. Если нет, мы имеем дело, что день не в целевом месяце, поэтому мы берем последний день месяца. Протестировано с помощью PHP 5.3.10.

<?php
$monthToAdd = 1;

$d1 = DateTime::createFromFormat('Y-m-d H:i:s', '2011-01-30 15:57:57');

$year = $d1->format('Y');
$month = $d1->format('n');
$day = $d1->format('d');

$year += floor($monthToAdd/12);
$monthToAdd = $monthToAdd%12;
$month += $monthToAdd;
if($month > 12) {
    $year ++;
    $month = $month % 12;
    if($month === 0)
        $month = 12;
}

if(!checkdate($month, $day, $year)) {
    $d2 = DateTime::createFromFormat('Y-n-j', $year.'-'.$month.'-1');
    $d2->modify('last day of');
}else {
    $d2 = DateTime::createFromFormat('Y-n-d', $year.'-'.$month.'-'.$day);
}
$d2->setTime($d1->format('H'), $d1->format('i'), $d1->format('s'));
echo $d2->format('Y-m-d H:i:s');

Ответ 2

У вас есть несколько альтернатив помимо DateInterval.

Вот примеры, которые используют strtotime():

http://www.brightcherry.co.uk/scribbles/php-adding-and-subtracting-dates/

// Subtracting days from a date
$date = "1998-08-14";
$newdate = strtotime ( '-3 day' , strtotime ( $date ) ) ;
$newdate = date ( 'Y-m-j' , $newdate );

echo $newdate;

...

// Subtracting months from a date
$date = "1998-08-14";
$newdate = strtotime ( '-3 month' , strtotime ( $date ) ) ;
$newdate = date ( 'Y-m-j' , $newdate );

echo $newdate;

Вот несколько ссылок для DateInterval:

Q: Точно как вы определяете "месяц" ?

Def # 1): "месяц" - "месяц" - независимо от #/дней

Def # 2): "месяц" составляет 30 дней (например)

Def # 3): "месяц" - это # ​​/дней между 1-м понедельником последующие месяцы

и т.д.. и т.д.

В: Каково ваше "определение"?

Ответ 3

ОК - насколько я могу судить, вы все еще не определили, что вы подразумеваете под "месяцем".

Но здесь еще одна функция, которая может помочь:

http://php.net/manual/en/function.getdate.php

/* Function to find the first and last day of the month from the given date.
*
* Author Binu v Pillai            [email protected]
* @Param            String             yyyy-mm-dd
*
*/
function findFirstAndLastDay($anyDate)
{
    //$anyDate            =    '2009-08-25';    // date format should be yyyy-mm-dd
    list($yr,$mn,$dt)    =    split('-',$anyDate);    // separate year, month and date
    $timeStamp            =    mktime(0,0,0,$mn,1,$yr);    //Create time stamp of the first day from the give date.
    $firstDay            =     date('D',$timeStamp);    //get first day of the given month
    list($y,$m,$t)        =     split('-',date('Y-m-t',$timeStamp)); //Find the last date of the month and separating it
    $lastDayTimeStamp    =    mktime(0,0,0,$m,$t,$y);//create time stamp of the last date of the give month
    $lastDay            =    date('D',$lastDayTimeStamp);// Find last day of the month
    $arrDay                =    array("$firstDay","$lastDay"); // return the result in an array format.

    return $arrDay;
}