У меня есть следующий код, который возвращает неожиданный ответ. Пожалуйста, дайте мне знать, что случилось.
$start_date = new DateTime('31-03-2019');
$end_date = new DateTime('01-05-2019');
$d = $start_date->diff($end_date);
echo "day: " . $d->d . " month: " . $d->m . "\n";
Он возвращает следующий вывод:
day: 0 month: 1
Я ожидаю, что вывод будет:
day: 1 month: 1
01-05-2019 ...это 1 мая или 5 января? Я спрашиваю об этом независимо от результата, который вы видите: всегда лучше предоставлять однозначные строки даты, чтобы избежать путаницы (не в последнюю очередь со стороны компьютера, который пытается ее обработать). (P.S. Я понимаю, что это, вероятно, 1 мая, поскольку дата выше явно указана в формате дд/мм/гггг, но компьютер не примет это во внимание)
Когда вы добавляете 1 месяц к 2019-03-31 (= увеличиваете номер месяца), вы получаете 2019-04-31. Поскольку в апреле всего 30 дней, 2019-04-31 — это то же представление, что и 2019-05-01. Таким образом, вы должны добавить ровно 1 месяц (и 0 дней) к исходной дате, чтобы получить целевую дату.
Проблема в том, что нет четкого определения месяца. Есть некоторое внутреннее определение, которое PHP использует для получения номера месяца, но оно бессодержательно. Это не просто разница между 03 и 05, потому что это было бы 2, и это также не очень помогает, если это период с середины февраля до середины апреля; это больше или меньше двух месяцев, если февраль короткий...? Итак, если вы хотите вычислить разницу в месяцах, вам лучше использовать свои собственные расчеты, которые соответствуют вашим ожиданиям. Или лучше вообще не пытаться найти такой плохо определенный номер.






Это даст вам один день и один месяц https://3v4l.org/q0T8r.
$start_date = new DateTime('31-03-2019 00:00:00');
$end_date = new DateTime('01-05-2019 24:00:00');
$d = $start_date->diff($end_date);
echo "day: " . $d->d . " month: " . $d->m . "\n";
Но в этом случае «31-03-2019» и «31-05-2019» становятся 2 месяца и 1 день.
Как это может быть 2 месяца, когда этот месяц почти закончился? Он округляет значение месяца.
с 31-03 по 31-05 у вас действительно есть 2 месяца, но с 31-03 по 01-05 у вас есть 1 месяц
см. stackoverflow.com/questions/3602405/…
Когда вы добавляете 1 месяц к 2019-03-31, PHP внутри просто увеличивает значение месяца 03 до 04. Результат 2019-04-31.
Поскольку в апреле всего 30 дней, 2019-04-31 имеет то же значение, что и 2019-05-01. И именно поэтому в результате вы получаете один месяц и ноль дней.
У класса DateInterval есть еще одно удобное свойство: days вместо m и d. Он будет содержать общее количество дней между двумя датами, равное 31 (вы должны добавить 31 день к 2019-03-31, чтобы получить 2019-05-01.
На этом значении вы можете реализовать свою собственную логику, что такое «один месяц». Если вы определите это как «один месяц = 30 дней», это может быть вашим желаемым результатом:
$start_date = new DateTime('31-03-2019');
$end_date = new DateTime('01-05-2019');
$diff = $start_date->diff($end_date);
$months = floor($diff->days / 30);
$days = $diff->days % 30;
echo "day: " . $days . " month: " . $months . "\n";
Кажется, PHP предполагает, что каждый месяц составляет 31 день.
Не уверен, но 1 месяц кажется правильным? Откуда вы хотите получить этот 1 день?