2014-09-12 3 views
0

Я хотел бы работать с PHP DateInterval перебирать месяцы:PHP: DatePeriod с последним днем ​​месяца

$from = new DateTime(); 
$from->setDate(2014, 1, 31); 

$period = new DatePeriod($from, new DateInterval('P1M'), 12); 

Я бы ожидать, что она вернется 31 января, 28 февраля (как DateInterval 1 месяц), но он фактически возвращается 31 января, 3 марта, 3 апреля ... следовательно, пропуская февраль.

Есть ли способ сделать это просто?

Спасибо!

EDIT: как Эталонное, вот это решение, которое, кажется, чтобы охватить большинство случаев использования:

$date = new DateTime('2014-01-31'); 
$start = $date->format('n'); 

for ($i = 0; $i < 28; $i++) { 
    $current = clone $date; 
    $current->modify('+'.$i.' month'); 

    if ($current->format('n') > ($start % 12) && $start !== 12) { 
    $current->modify('last day of last month'); 
    } 

    $start++; 

    echo $current->format('Y-m-d').PHP_EOL; 
} 

ответ

0

Вы можете попробовать так:

$date = new DateTime(); 
$lastDayOfMonth = $date->modify(
    sprintf('+%d days', $date->format('t') - $date->format('j')) 
); 
2

Вы можете использовать DateTime::modify():

$date = new DateTime('last day of january'); 
echo $date->format('Y-m-d').PHP_EOL; 

for ($i = 1; $i < 12; $i++) { 
    $date->modify('last day of next month'); 
    echo $date->format('Y-m-d').PHP_EOL; 
} 

EDIT: Я думаю, что не понял и ваш вопрос четко. Вот новая версия:

$date = new DateTime('2014-01-31'); 

for ($i = 0; $i < 12; $i++) { 
    $current = clone $date; 
    $current->modify('+'.$i.' month'); 

    if ($current->format('n') > $i + 1) { 
    $current->modify('last day of last month'); 
    } 

    echo $current->format('Y-m-d').PHP_EOL; 
} 
+0

это работает только, если вам нужно в последний день месяц. На самом деле я хочу повторить и заставить его работать во всех случаях (поэтому он также должен работать, повторяя каждый месяц, начиная с 2 января, например). –

+0

Я вижу. Обновлен мой ответ с новым кодом. Можете ли вы протестировать его и сообщить мне, если это то, что вы хотели? –

+0

Да, я пробовал различные кромки с февраля и, похоже, работает отлично! (хотя я по-прежнему считаю, что поведение DatePeriod нелогично ...). Большое спасибо –

0

Я хотел бы сделать это, вероятно, как этот

$max = array (
31,28,31,30,31,30,31,31,30,31,30,31 
); //days in month 

$month = 1; 
$year = 2014; 
$day = 31; 

$iterate = 12; 
$dates = array(); 
for ($i = 0;$i < $iterate;$i++) { 
    $tmp_month = ($month + $i) % 12; 
    $tmp_year = $year + floor($month+$i)/12; 
    $tmp_day = min($day, $max[$tmp_month]); 
    $tmp = new DateTime(); 
    $tmp->setDate($tmp_year, $tmp_month + 1, $tmp_day); 
    $dates[] = $tmp; 
} 

var_dump($dates); 

Это держит в тот же день каждый месяц, если это возможно

+0

Это похоже на «менее плохое» решение. Хотя я боюсь ему потребуются некоторые настройки (например, с учетом лет, в которых в феврале 29 дней). –

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