2012-01-03 3 views
1

Мне нужен метод добавления некоторого количества месяцев в любую дату на PHP. Я знаю, как это сделать в MySQL, но не в PHP. Вот моя попытка:Нужно добавить количество месяцев в дату

MySQL:

SELECT DATE_ADD('2011-12-29', INTERVAL 2 
    MONTH) // Output "2012-02-29" 

    SELECT DATE_ADD('2011-12-30', INTERVAL 2 
    MONTH) // output "2012-02-29" 

    SELECT DATE_ADD('2011-12-31', INTERVAL 2 
    MONTH) // output "2012-02-29" 

PHP:

$date = date_create('2011-12-29'); 
    $date->modify("+1 month"); 
    echo $date->format("Y-m-d"); 
    // Output is "2012-01-29" -- this is correct 

    $date = date_create('2011-12-30'); 
    $date->modify("+2 month"); 
    echo $date->format("Y-m-d"); 
    // Output is "2012-03-01" -- I need the answer like "2012-02-29" 

    $date = date_create('2011-12-31'); 
    $date->modify("+2 month"); 
    echo $date->format("Y-m-d"); 
    // Output is "2012-03-02" -- I need the answer like "2012-02-29" 

Выход MySQL правильно. Мне нужен тот же вывод в PHP.

+1

http://stackoverflow.com/questions/3602405/php-datetimemodify-adding-and-subtracting-months –

+0

это может помочь вам http://stackoverflow.com/questions/8085886/add-days-to-a -date-in-php и http://stackoverflow.com/questions/3812929/adding-months-to-a-existing-date – Arfeen

+0

вам придется катиться самостоятельно, потому что 2011-12-31 + 2 месяца не является 12-02-29 ... в PHP нет ничего, что будет готово округлить, если вы выше 29. – dqhendricks

ответ

1

Вот решение, которое может сделать работу для вас:

function addMonths(DateTime $date, $months) { 
    $last = clone $date; 
    $last = $last->modify("last day of +$months months")->getTimestamp(); 

    $default = clone $date; 
    $default = $default->modify("+$months months")->getTimestamp(); 

    return $date->setTimestamp(min($last, $default)); 
} 

$date = new DateTime('2011-12-31'); 
$laterDate = addMonths($date, 2); 

Это будет работать независимо от того, какой день месяца вы начинаете с.

0

Надеюсь, вам это наверняка поможет.

Я просто пытаюсь с добавлением дней вместо добавления месяцев

$MonthAdded = strtotime("+60 days",strtotime('2011-12-31')); 
echo "After adding month: ".date('Y-m-d', $MonthAdded)."<br>"; 

Выход:

After adding month: 2012-02-29 
+0

Это просто счастливое совпадение - январь имеет 31 день, в этом феврале - 29 дней, поэтому 31 + 29 = 60. Для 'strtotime (« + 60 дней », strtotime (« 2012-12-31 »)); получить 2013-03-01. – Crontab

0

Читать ссылку Дагон писал в комментариях к вашему вопросу. Экстраполяция на ответ там, я попробовал это, и она работает:

$d = new DateTime("2011-12-31"); 
$d->modify("last day of +2 months"); 
echo $d->format("Y-m-d"); 
// result is 2012-02-29 

$d = new DateTime("2012-12-31"); 
$d->modify("last day of +2 months"); 
echo $d->format("Y-m-d"); 
// result is 2013-02-28 
+0

Прекрасно работает, если последний день нужен, но задыхается, если '$ d = новый DateTime (" 2011-12-01 ");', и вопрос, кажется, предполагает, что он хочет решение для любой даты. – cmbuckley

+0

Я тестировал его на PHP 5.3.5, и он отлично работает, если я использую 2011-12-01 в качестве даты.Судя по первым трем примерам, которые автор дал (12/29, 12/30 и 12/31, все ожидали последнего дня февраля в качестве ответа), я понял, что автор действительно хотел, чтобы последний день месяца два месяца с указанной даты. – Crontab

+0

Хотя я понимаю, откуда вы, cbuckley. – Crontab

2

Если вы используете PHP5> = 5.3, все, что вам нужно сделать, это использовать

$date->modify("last day of +2 months"); 

как предложено в других ответах. Но если вы используете 5.2, вы можете попробовать изменять свой код так:

Class DateTimeM Extends DateTime 
{ 
    public function modify ($modify) 
    { 
      $day = $this->format ('d'); 
      $buf = new DateTime ($this->format ('Y-m-01\TH:i:sO')); 
      $buf->modify ($modify); 
      if ($day > $buf->format ('t')) 
      { 
        $this->setDate ($buf->format ('Y'), $buf->format ('m'), $buf->format ('t')); 
      } 
      else 
      { 
        $this->setDate ($buf->format ('Y'), $buf->format ('m'), $day); 
      } 
      $this->setTime ($buf->format ('H'), $buf->format ('i'), $buf->format ('s')); 

      return $this; 
     } 
} 

$date = new DateTimeM ('2011-12-29'); 
$date->modify("+2 month"); 
echo $date->format("Y-m-d"); 

Я предлагаю добавить определение класса в отдельный файл и require_once() его. Переключитесь с date_create() на использование конструктора объектов нового класса. Метод modify() нового класса изменит дату, используя первый день исходного месяца, а не последний, и проверьте, превышает ли исходный заданный день месяца число дней нового месяца.

Преимущество этого подхода состоит в том, что он будет работать, например, для $date->modify ('2 year 2 month').

+0

+1, но я считаю, что третий параметр для 'setDate' в условии else должен быть' $ day'. – cmbuckley

+0

@cbuckley: Вы абсолютно правы, спасибо! – zrvan

Смежные вопросы