DateTime::diff возвращает неожиданный результат

У меня есть следующий код, который возвращает неожиданный ответ. Пожалуйста, дайте мне знать, что случилось.

$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

Не уверен, но 1 месяц кажется правильным? Откуда вы хотите получить этот 1 день?

Tomm 01.03.2019 14:49

01-05-2019 ...это 1 мая или 5 января? Я спрашиваю об этом независимо от результата, который вы видите: всегда лучше предоставлять однозначные строки даты, чтобы избежать путаницы (не в последнюю очередь со стороны компьютера, который пытается ее обработать). (P.S. Я понимаю, что это, вероятно, 1 мая, поскольку дата выше явно указана в формате дд/мм/гггг, но компьютер не примет это во внимание)

ADyson 01.03.2019 14:49

Когда вы добавляете 1 месяц к 2019-03-31 (= увеличиваете номер месяца), вы получаете 2019-04-31. Поскольку в апреле всего 30 дней, 2019-04-31 — это то же представление, что и 2019-05-01. Таким образом, вы должны добавить ровно 1 месяц (и 0 дней) к исходной дате, чтобы получить целевую дату.

Wulf 01.03.2019 14:52

Проблема в том, что нет четкого определения месяца. Есть некоторое внутреннее определение, которое PHP использует для получения номера месяца, но оно бессодержательно. Это не просто разница между 03 и 05, потому что это было бы 2, и это также не очень помогает, если это период с середины февраля до середины апреля; это больше или меньше двух месяцев, если февраль короткий...? Итак, если вы хотите вычислить разницу в месяцах, вам лучше использовать свои собственные расчеты, которые соответствуют вашим ожиданиям. Или лучше вообще не пытаться найти такой плохо определенный номер.

deceze 01.03.2019 14:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
4
4
65
2

Ответы 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 день.

moeseth 01.03.2019 15:00

Как это может быть 2 месяца, когда этот месяц почти закончился? Он округляет значение месяца.

Andrei Lupuleasa 01.03.2019 15:05

с 31-03 по 31-05 у вас действительно есть 2 месяца, но с 31-03 по 01-05 у вас есть 1 месяц

Andrei Lupuleasa 01.03.2019 15:13

см. stackoverflow.com/questions/3602405/…

Andrei Lupuleasa 01.03.2019 19:13

Когда вы добавляете 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 день.

moeseth 01.03.2019 15:10

Другие вопросы по теме