2013-07-26 2 views
4

Я использую следующий код:PHP DateInterval не возвращает последний день месяца

public static function getDays($day, $m, $y) { 
    $days = new DatePeriod(
    new DateTime("first $day of $m $y"), 
    DateInterval::createFromDateString('next ' . $day), 
    new DateTime("last day of $m $y") 
); 
    foreach ($days as $day) { 
    $dates[] = $day->format("Y-m-d"); 
    } 
    return $dates; 
} 

Это работа для большей части. Я даю ему диапазон, и он возвращает дату каждого дня, когда я буду внутри диапазона.

Использование:

foreach(General::getDays('friday',$this->_uri[2],$this->_uri[3]) as $date) { 
    var_dump($date); 
} 

В июле 2013 года, это возвращает правильные 4 результаты, все Пятницы в июле 2013 года:

string '2013-07-05' (length=10) 
string '2013-07-12' (length=10) 
string '2013-07-19' (length=10) 
string '2013-07-26' (length=10) 

Однако, на месяц, что последний день является матч день, прошедший после (пятница, например, май 2013 года и январь 2014 года), он пропускает последний день месяца из возвращаемых результатов.

мая 2013 результаты, пропавшие конечно 31-й, который является пятница:

string '2013-05-03' (length=10) 
string '2013-05-10' (length=10) 
string '2013-05-17' (length=10) 
string '2013-05-24' (length=10) 

Кто-нибудь есть ответ на это? Является ли это моим промахом DateInterval или подлинной ошибкой в ​​этом классе?

+0

Интересно, если бы лучше удачи, если вы выбрали «день и время» - что-то другое, кроме полуночи. Что-то фанки может происходить с помощью сравнения '<' vs '<='. Я кратко подумал, что может быть проблема с DST, но это неправильные месяцы для этого ... – Floris

ответ

5

Проблема заключается в том, что сама дата окончания/времени никогда не включается в период - то есть объект DatePeriod представляет дату/время в диапазоне [$startDate, $endDate).

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

$days = new DatePeriod(
    new DateTime("first $day of $m $y"), 
    DateInterval::createFromDateString('next ' . $day), 
    new DateTime("last day of $m $y 00:01") 
); 

¹, если вы не используете DatePeriod::EXCLUDE_START_DATE вариант, в этом случае дата начала сама исключается, а

+0

Большое спасибо. Это ударило ногой по голове. –

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