Date diff: примеры (PHP)

Полное руководство по date_diff: вычисление интервалов между датами в PHP
Раздел: Дата и время
date_diff(DateTimeInterface $baseObject, DateTimeInterface $targetObject, bool $absolute = false): DateInterval

Функция date_diff() возвращает разницу между двумя объектами DateTime. Она также известна под псевдонимом DateTime::diff(). Её применение актуально при необходимости вычислить интервал между двумя датами.

Синтаксис и параметры

Функция имеет два основных формата вызова:

date_diff(DateTimeInterface $baseObject, DateTimeInterface $targetObject, bool $absolute = false): DateInterval|false
$datetime1->diff($datetime2, $absolute);
  • $baseObject (DateTimeInterface): Начальная дата/время.
  • $targetObject (DateTimeInterface): Конечная дата/время.
  • $absolute (bool, необязательный): Если установлено в true, функция возвращает абсолютную (положительную) разницу. По умолчанию false, что может дать отрицательные компоненты интервала, если первая дата больше второй.

Функция возвращает объект DateInterval, содержащий компоненты разницы (годы, месяцы, дни, часы и т.д.), или false в случае ошибки.

Краткие примеры использования

Пример 1: Базовая разница между датами.

$date1 = date_create('2023-01-01');
$date2 = date_create('2023-12-31');
$interval = date_diff($date1, $date2);
echo $interval->format('%R%a дней');
+364 дней

Пример 2: Использование объектно-ориентированного стиля и абсолютного значения.

$datetime1 = new DateTime('2024-06-15 10:30:00');
$datetime2 = new DateTime('2024-06-10 14:00:00');
$interval = $datetime1->diff($datetime2, true); // Абсолютная разница
echo $interval->format('%d дней, %h часов, %i минут');
4 дней, 20 часов, 30 минут

Пример 3: Разница с отрицательными компонентами (без флага absolute).

$past = new DateTime('2024-01-10');
$future = new DateTime('2024-01-05');
$interval = $past->diff($future);
echo $interval->format('%R%a дней'); // Знак минус
print_r($interval);
-5 дней
DateInterval Object
(
    [y] => 0
    [m] => 0
    [d] => -5
    [h] => 0
    [i] => 0
    [s] => 0
    ...
)
Похожие функции в PHP
  • strtotime() и арифметика: Для простых вычислений с секундами.
    $diff_days = (strtotime('2024-12-31') - strtotime('2024-01-01')) / (60*60*24);
    Не учитывает часовые пояса и переход на летнее время для интервалов.
  • gmdate() и mktime(): Устаревший подход для расчетов на уровне временных меток.
  • DateInterval в конструкторе: Создание интервала напрямую (new DateInterval('P1D')), но не для вычисления разницы.

Функция date_diff() предпочтительна для точных, комплексных расчетов с датами, так как работает с объектами DateTime и корректно обрабатывает временные зоны и високосные годы.

Типичные ошибки

Ошибка 1: Передача неверного типа аргумента.

$interval = date_diff('2024-01-01', new DateTime()); // Ошибка
TypeError: date_diff(): Argument #1 ($baseObject) must be of type DateTimeInterface, string given

Ошибка 2: Неверное использование форматирования объекта DateInterval.

$interval = date_diff(new DateTime('2024-01-01'), new DateTime('2024-02-01'));
echo $interval->days; // Корректно, общее количество дней
// echo $interval->day; // Ошибка, свойства 'day' не существует

Ошибка 3: Игнорирование микросекунд. До PHP 8.1 date_diff() обнулял микросекунды.

// PHP 8.0 и ранее:
$date1 = new DateTime('2024-01-01 12:00:00.500000');
$date2 = new DateTime('2024-01-01 12:00:00.600000');
$interval = $date1->diff($date2);
echo $interval->format('%f'); // Выводило 0
0
Изменения в последних версиях PHP
  • PHP 8.1.0: Функция стала учитывать микросекунды при расчете разницы. В более ранних версиях микросекунды обнулялись.
  • PHP 8.0.0: Функция теперь возвращает DateInterval|false. Ранее возвращался DateInterval или false в случае ошибки, но сигнатура не была строгой.
  • PHP 7.2.0: Константа DateInterval::INVERT стала публичной.
Расширенные примеры

Пример 1: Расчет точного возраста с учетом времени суток.

Пример php
$birthday = new DateTime('1985-07-15 14:30:00');
$today = new DateTime('2024-06-10 09:15:00');
$age = $birthday->diff($today);
echo "Полных лет: {$age->y}, месяцев: {$age->m}, дней: {$age->d}";
echo "\nВсего дней с рождения: " . $age->days;
Полных лет: 38, месяцев: 10, дней: 25
Всего дней с рождения: 14198

Пример 2: Работа с интервалами, превышающими диапазон (использование свойства days).

Пример php
$date1 = date_create('0001-01-01');
$date2 = date_create('2024-01-01');
$interval = date_diff($date1, $date2);
// Свойства y, m, d покажут корректную разницу, но есть ограничения
// Свойство days доступно только для разниц, рассчитанных через diff()
echo "Годы: {$interval->y}, Общее количество дней: {$interval->days}";
Годы: 2023, Общее количество дней: 739122

Пример 3: Цепочка вычислений и изменение интервала.

Пример php
$start = new DateTime('2024-01-01');
$end = new DateTime('2024-03-15');
$interval = $start->diff($end);
// Добавление интервала к дате
$new_date = clone $start;
$new_date->add($interval);
echo $new_date->format('Y-m-d'); // 2024-03-15
// Использование интервала для периодичности
$period = new DatePeriod($start, new DateInterval('P1M'), 5); // 5 месяцев
foreach ($period as $date) {
    echo $date->format('Y-m'), "\n";
}
2024-03-15
2024-01
2024-02
2024-03
2024-04
2024-05
Аналоги в других языках
Python (datetime.timedelta)
from datetime import datetime
date1 = datetime(2024, 6, 15)
date2 = datetime(2024, 6, 10)
difference = date2 - date1  # date1 - date2 даст отрицательный timedelta
print(difference.days)  # -5
print(abs(difference.days))  # 5
-5
5

В Python разница возвращает объект timedelta, который может быть отрицательным. Нет отдельных компонентов для месяцев и лет из-за их переменной длины.

JavaScript (Date object, milliseconds)
let date1 = new Date('2024-06-15');
let date2 = new Date('2024-06-10');
let diffTime = date2 - date1; // Разница в миллисекундах
let diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
console.log(diffDays);
-5

В JavaScript разница вычисляется в миллисекундах. Для получения компонентов (дней, месяцев) требуется ручной расчет или использование библиотек (например, Moment.js).

MySQL (DATEDIFF, TIMESTAMPDIFF)
-- Разница в днях
SELECT DATEDIFF('2024-06-10', '2024-06-15') AS diff_days;
-- Разница в месяцах
SELECT TIMESTAMPDIFF(MONTH, '2024-01-15', '2024-06-20') AS diff_months;
diff_days: -5
diff_months: 5

SQL-функции работают на уровне запроса к БД и возвращают скалярные значения (целые числа) для выбранной единицы измерения.

PHP date_diff function comments

En
Date diff Alias of DateTime::diff