Avatar ·

Как вычислить количество дней между двумя датами в PHP?

Всем привет! Я новичок в PHP и никак не могу разобраться с датами. Мне нужно написать скрипт, который считает количество дней между двумя датами. Например, я хочу узнать, сколько дней прошло с начала года до сегодняшнего дня, или сколько осталось до Нового года. Я пробовал что-то вроде этого: ```php $date1 = '2023-01-01'; $date2 = '2023-12-31'; $days = ($date2 - $date1) / (60 * 60 * 24); echo $days; ``` Но это не работает — выводит какую-то ерунду или ошибку. Я понимаю, что строки так не вычитаются, но как правильно? В интернете много разных советов: кто-то советует `strtotime()`, кто-то — `DateTime`, а кто-то — `date_diff`. Я совсем запутался. Подскажите, пожалуйста, самый правильный и современный способ найти разницу в днях между двумя датами в PHP. Важно, чтобы решение работало с датами в разных форматах (например, `2023-01-01` или `01.01.2023`) и учитывало високосные годы. Заранее спасибо! <<>>

Использование класса DateTime (рекомендуемый способ)

Самый правильный и современный способ в PHP — использовать встроенный класс DateTime вместе с методом diff(). Этот подход учитывает все тонкости: високосные годы, разные часовые пояса и форматы дат.

Вот базовый пример:

<?php
$date1 = new DateTime('2023-01-01');
$date2 = new DateTime('2023-12-31');
$interval = $date1->diff($date2);
echo $interval->days; // Выведет: 364
?>

Обратите внимание: мы используем свойство days, а не format('%a') — это одно и то же, но days короче. Если нужно получить разницу в других единицах (годы, месяцы, дни), можно использовать format():

<?php
echo $interval->format('%y years, %m months, %d days');
// Выведет: 0 years, 11 months, 30 days
?>

Работа с разными форматами дат

Класс DateTime умеет парсить большинство распространённых форматов. Если формат нестандартный, используйте DateTime::createFromFormat():

<?php
$date1 = DateTime::createFromFormat('d.m.Y', '01.01.2023');
$date2 = DateTime::createFromFormat('d.m.Y', '31.12.2023');
$interval = $date1->diff($date2);
echo $interval->days; // 364
?>

Учёт времени и часовых поясов

Если даты содержат время, diff() всё равно корректно посчитает разницу. Но будьте осторожны с часовыми поясами — лучше явно задавать их:

<?php
$date1 = new DateTime('2023-01-01 12:00:00', new DateTimeZone('Europe/Moscow'));
$date2 = new DateTime('2023-01-02 12:00:00', new DateTimeZone('Europe/Moscow'));
$interval = $date1->diff($date2);
echo $interval->days; // 1
?>

Проверка: какая дата больше?

Если вы не знаете, какая дата раньше, diff() всё равно вернёт положительное число. Но можно проверить знак через $interval->invert (1 = отрицательный результат):

<?php
$date1 = new DateTime('2023-12-31');
$date2 = new DateTime('2023-01-01');
$interval = $date1->diff($date2);
if ($interval->invert) {
    echo "Вторая дата раньше первой";
} else {
    echo "Разница: " . $interval->days . " дней";
}
?>

Почему это лучший способ?

  • Объектно-ориентированный — современный стандарт PHP.
  • Учитывает високосные годы — 2024 год (високосный) будет обработан корректно.
  • Работает с датами до 2038 года — в отличие от старых функций.
  • Гибкость — легко менять форматы, добавлять часовые пояса.

Этот код будет работать на PHP 5.2+ (класс DateTime появился в PHP 5.2) и на всех современных версиях.

<<>>

Альтернатива: использование strtotime()

Если вы работаете с очень старым кодом или по каким-то причинам не можете использовать класс DateTime, можно применить функцию strtotime(). Она преобразует текстовую дату в Unix-метку (количество секунд с 1 января 1970 года), после чего разницу легко вычислить:

<?php
$date1 = strtotime('2023-01-01');
$date2 = strtotime('2023-12-31');
$seconds_diff = $date2 - $date1;
$days = floor($seconds_diff / (60 * 60 * 24));
echo $days; // 364
?>

Важные нюансы:

  • Используйте floor() для округления вниз, так как разница в секундах может дать дробное число из-за перехода на летнее время.
  • Функция strtotime() ограничена диапазоном дат с 1901 по 2038 год (на 32-битных системах).
  • Не все форматы дат распознаются — например, 01.01.2023 нужно преобразовать в 2023-01-01.

Этот способ проще для понимания новичками, но менее гибкий и надёжный, чем DateTime. Рекомендую использовать его только для простых скриптов или в учебных целях.