Получение из разницы дат

Работа с разницей между датами в Luxon строится вокруг объектов DateTime и специализированного класса Duration, который представляет не момент времени, а промежуток между двумя моментами. В отличие от стандартного Date, Luxon учитывает временные зоны, календарные особенности и корректно работает с единицами измерения времени, что делает вычисление разницы дат предсказуемым и точным.

Разница между датами в Luxon не возвращается в виде числа миллисекунд по умолчанию. Вместо этого результатом является объект длительности, который может быть представлен в различных единицах: днях, часах, минутах, секундах и их комбинациях.

Основной метод для вычисления разницы:

const diff = dt1.diff(dt2);

Где:

  • dt1 — более поздняя дата (или базовая точка отсчёта)
  • dt2 — более ранняя дата

Результатом является объект Duration.

Пример

import { DateTime } from "luxon";

const start = DateTime.fromISO("2026-01-01T00:00:00");
const end = DateTime.fromISO("2026-01-10T12:00:00");

const diff = end.diff(start);

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


Указание единиц измерения

Ключевая особенность diff — возможность задавать единицы измерения разницы.

end.diff(start, ["days"]);

Поддерживаемые единицы:

  • milliseconds
  • seconds
  • minutes
  • hours
  • days
  • weeks
  • months
  • years

Пример: разница в днях

const diffInDays = end.diff(start, "days");
console.log(diffInDays.days);

Результат будет дробным, если разница не кратна суткам.


Множественные единицы

Luxon позволяет получать сразу несколько единиц в одном объекте длительности.

const diff = end.diff(start, ["days", "hours", "minutes"]);

Результат:

diff.days
diff.hours
diff.minutes

Важно: значения распределяются по иерархии единиц, но не нормализуются автоматически без дополнительных методов.


Нормализация длительности

Для приведения результата к корректной структуре используется метод normalize().

const diff = end.diff(start, ["days", "hours"]).normalize();

Без нормализации возможно получение значений вида:

  • 1.5 days
  • 36 hours (в зависимости от единиц)

После нормализации происходит перераспределение значений по единицам.


Разница относительно текущего времени

Частый сценарий — вычисление разницы между датой и текущим моментом.

Метод diffNow

const dt = DateTime.fromISO("2026-12-01");
const diff = dt.diffNow("days");

Если дата в будущем — результат положительный, если в прошлом — отрицательный.


Абсолютная разница

Для получения модуля разницы используется as() или toMillis() с последующей обработкой.

const diff = Math.abs(end.diff(start).as("days"));

Или:

const diff = end.diff(start).toMillis();
const abs = Math.abs(diff);

Форматирование результата

Объект Duration может быть преобразован в человекочитаемый вид.

toObject()

const diff = end.diff(start, ["days", "hours"]);
console.log(diff.toObject());

Результат:

{ days: 9, hours: 12 }

toHuman()

Метод формирует строку с автоматическим форматированием.

diff.toHuman();

Пример результата:

9 days, 12 hours

Работа с дробными значениями

Luxon сохраняет точность при вычислении дробных интервалов.

const diff = end.diff(start, "days");
console.log(diff.days); // например 9.5

Это особенно важно при:

  • расчётах графиков
  • биллинге по времени
  • аналитике событий

Учёт временных зон

Разница дат всегда вычисляется с учётом временной зоны объектов DateTime.

const a = DateTime.fromISO("2026-01-01T00:00", { zone: "Europe/Paris" });
const b = DateTime.fromISO("2026-01-01T00:00", { zone: "UTC" });

const diff = a.diff(b, "hours");

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


Сравнение diff и until

Метод until является альтернативой:

const interval = start.until(end);

Разница:

  • diff → возвращает Duration
  • until → возвращает Interval

Далее:

interval.length("days");

Interval удобен для анализа диапазонов, а Duration — для арифметики времени.


Ограничения и особенности вычислений

1. Календарные единицы

Месяцы и годы не фиксированы по длительности:

  • 1 месяц = 28–31 день
  • 1 год = 365 или 366 дней

Поэтому:

end.diff(start, "months");

может давать неравномерные результаты при конвертации в дни.


2. Потеря точности при смешанных единицах

При использовании комбинаций единиц важно учитывать порядок нормализации:

end.diff(start, ["months", "days"]).normalize();

Без нормализации часть данных может оставаться “переполненной”.


3. Обратная разница

Порядок аргументов критичен:

a.diff(b)

и

b.diff(a)

дают одинаковую величину, но с разным знаком.


Практические сценарии использования

Подсчёт возраста

const birth = DateTime.fromISO("2000-05-10");
const age = DateTime.now().diff(birth, "years").years;

Таймер обратного отсчёта

const event = DateTime.fromISO("2026-12-31T23:59");
const remaining = event.diffNow(["days", "hours", "minutes"]);

Учёт рабочего времени

const start = DateTime.fromISO("2026-05-23T09:00");
const end = DateTime.fromISO("2026-05-23T18:30");

const work = end.diff(start, "hours").hours;

Аналитика событий

const first = DateTime.fromISO("2026-01-01");
const second = DateTime.fromISO("2026-06-01");

const diff = second.diff(first, ["days"]);

Используется для:

  • анализа роста показателей
  • интервалов между событиями
  • временных метрик

Преобразование длительности в другие форматы

В миллисекунды

diff.as("milliseconds");

В секунды

diff.as("seconds");

В часы

diff.as("hours");

Сравнение точности: Luxon и стандартный Date

Стандартный подход:

const diff = (end - start) / (1000 * 60 * 60 * 24);

Luxon:

end.diff(start, "days").days;

Различия:

  • Luxon учитывает таймзоны
  • поддерживает календарные единицы
  • возвращает структурированный результат
  • исключает ручные пересчёты

Комбинирование с округлением

Для контроля точности используется округление:

const diff = end.diff(start, "days").mapUnits(x => Math.floor(x));

Это позволяет фиксировать:

  • целые дни
  • целые часы
  • бизнес-логики без дробей

Работа с отрицательными интервалами

Luxon не ограничивает направление разницы:

const diff = start.diff(end, "days");

Результат будет отрицательным Duration, что полезно для:

  • обратных отсчётов
  • проверки просрочки
  • логики дедлайнов