Как гарантированно получить дату месяца из списка?
Мне нужно получить даты из прошлого основываясь на стартовой дате, которую указал пользователь. Например, если пользователь указал 05.12.2020, я должен получить все 5 числа до сегодняшней даты:
05.12.2020
05.01.2021
05.02.2021
05.03.2021
05.04.2021
05.05.2021
05.06.2021
Если пользователь указал 10.12.2020, я должен получить все 5 числа до сегодняшней даты:
05.12.2020
05.01.2021
05.02.2021
05.03.2021
05.04.2021
05.05.2021
09.06.2021 <<<
Код ниже выполняет данную задачу:
<?php
$begin = new DateTime( '05-12-2020' );
$end = new DateTime( date('d-m-Y') );
$end = $end->modify( '+31 day' ); //month
$interval = new DateInterval('P1M'); //31D
$daterange = new DatePeriod($begin, $interval ,$end);
foreach($daterange as $date){
echo $date->format('d-m-Y') . '<br>' . PHP_EOL;
}
Но добавляет не существующую сегодня итоговую дату 05-07-2021
05-12-2020
05-01-2021
05-02-2021
05-03-2021
05-04-2021
05-05-2021
05-06-2021
05-07-2021
Если отредактировать строку $end = $end->modify( '+31 day' ); //month и поставить 20 дней, то код работает корректно, видимо это зависит от сегодняшней даты и в 20 числах он слетит.
Чтобы не путать вас, напишу то, что в итоге хочу получить.
Если пользователь указал дату 31.12.2019, мне нужен список месяцев с датами 31 и если в конкретном месяце нет 31 числа, то проставить последнюю дату данного месяца (26,27,28,29,30) но далее проставлять 31 числа. Если в текущем месяце 31 не наступило, проставить текущую дату.
Если сейчас в приведенном выше коде указать дату как 31 число, то даты сбиваются, так:
31-12-2020
31-01-2021
03-03-2021
03-04-2021
03-05-2021
03-06-2021
03-07-2021 <<<
Т.е. существует 2 проблемы:
1 конечный день месяца;
2 отображение в результате даты, которая еще не наступила.
Как реализовать?
Ответы (1 шт):
На основе этого ответа https://stackoverflow.com/questions/5760262/php-adding-months-to-a-date-while-not-exceeding-the-last-day-of-the-month
Суть в том, что если к 31 января 2021 года добавить 1 месяц, то будет не 28 февраля 2021, как предполагается логически, а 2 марта 2021, это и порождает проблемы.
Вот мой вариант вывода дат:
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;
}
function print_dates($date_str_begin) {
$i = 0;
$date_for_while = DateTime::createFromFormat('Y-m-d', $date_str_begin);
while ($date_for_while->getTimestamp() < time()) {
//прибавить месяц через функцию
$date = add($date_str_begin, $i);
//вывести на экран
echo $date->format('Y-m-d') . '<br>';
//тупо для завершения цикла
$date_for_while->modify('+1 month');
//для add()
$i++;
}
}
$date_str = '2020-12-31';
print_dates($date_str);
echo "\n\n<br>";
$date_str = '2020-12-05';
print_dates($date_str);
//2020-12-31
//2021-01-31
//2021-02-28
//2021-03-31
//2021-04-30
//2021-05-31
//
//2020-12-05
//2021-01-05
//2021-02-05
//2021-03-05
//2021-04-05
//2021-05-05
//2021-06-05