Объект Duration как аргумент

В библиотеке Luxon объект Duration представляет собой строго типизированное описание временного интервала. В отличие от обычных числовых смещений (миллисекунды), Duration хранит семантические единицы времени: годы, месяцы, дни, часы, минуты, секунды и миллисекунды. Это делает его ключевым инструментом при работе с календарной арифметикой.

В контексте API Luxon Duration часто используется не как самостоятельная сущность, а как аргумент в методах работы с датами и другими длительностями.


Роль Duration в аргументах методов

Основная идея использования Duration как аргумента заключается в передаче не «сырого числа», а структурированного временного интервала.

Типичные сценарии:

  • смещение даты вперёд или назад;
  • вычисление новых временных точек;
  • комбинирование интервалов;
  • нормализация сложных временных выражений.

DateTime.plus(Duration) и DateTime.minus(Duration)

Наиболее важное место применения Duration — методы plus и minus.

DateTime.plus

Метод принимает объект Duration или его эквивалентное описание:

import { DateTime, Duration } from "luxon";

const dt = DateTime.local(2026, 1, 1);

const dur = Duration.fromObject({
  days: 10,
  hours: 5
});

const result = dt.plus(dur);

Логика работы:

  • происходит разбор Duration на календарные единицы;
  • добавление выполняется с учётом календарных правил (месяцы, переходы через границы);
  • результатом становится новый DateTime.

DateTime.minus

Работает симметрично plus, но выполняет обратное смещение:

const dur = Duration.fromObject({
  weeks: 2,
  minutes: 30
});

const result = DateTime.now().minus(dur);

Особенность:

  • сохраняется календарная точность;
  • вычитание месяцев и лет учитывает длину месяцев, включая високосные годы.

Duration как альтернативный формат входных данных

Luxon допускает передачу не только экземпляра Duration, но и «duration-like» объекта.

Пример:

DateTime.local().plus({ hours: 3, minutes: 15 });

В этом случае происходит автоматическая конвертация в Duration внутри метода. Фактически создаётся промежуточный объект:

Duration.fromObject({ hours: 3, minutes: 15 });

Такой подход позволяет:

  • сокращать код;
  • избегать явного создания Duration;
  • сохранять читаемость при простых смещениях.

Duration в цепочках операций

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

const result = DateTime.local()
  .plus(Duration.fromObject({ days: 1 }))
  .minus(Duration.fromObject({ hours: 2 }))
  .plus({ minutes: 45 });

Механика:

  • каждый шаг возвращает новый DateTime;
  • Duration применяется как чистый описательный слой;
  • не происходит мутации исходного объекта.

Использование Duration с diff-операциями

Метод diff возвращает Duration, но также может принимать Duration как параметр для нормализации результата.

const a = DateTime.local(2026, 1, 1);
const b = DateTime.local(2026, 1, 10);

const diff = b.diff(a);

Результат — Duration, который затем может быть снова использован как аргумент:

const normalized = a.plus(diff);

Это создаёт замкнутый цикл преобразований:

  • DateTime → Duration → DateTime

Передача Duration в пользовательские функции

Duration часто используется как унифицированный аргумент в прикладных функциях:

function scheduleEvent(start, duration) {
  return start.plus(duration);
}

const start = DateTime.local(2026, 5, 23);

const result = scheduleEvent(
  start,
  Duration.fromObject({ hours: 2, minutes: 30 })
);

Преимущество такого подхода:

  • единый формат временных интервалов;
  • отсутствие неоднозначности (миллисекунды vs календарные единицы);
  • упрощение тестирования.

Нормализация Duration перед передачей

Перед использованием в качестве аргумента Duration часто приводится к канонической форме:

const dur = Duration.fromObject({
  hours: 25,
  minutes: 120
}).normalize();

После нормализации:

  • 120 минут превращаются в 2 часа;
  • 25 часов преобразуются в 1 день и 1 час.

При передаче в plus или minus это снижает риск неоднозначных интерпретаций.


Ограничения при использовании Duration как аргумента

При передаче Duration в методы DateTime существуют важные особенности:

  1. Календарная неоднозначность

    • месяцы и годы не имеют фиксированной длины;
    • результат зависит от исходной даты.
  2. Различие между фиксированным и календарным временем

    • Duration не эквивалентен миллисекундам;
    • операции не всегда линейны.
  3. Приоритет единиц

    • более крупные единицы (years, months) обрабатываются отдельно от точных временных значений.

Конвертация Duration в примитивные значения

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

const ms = Duration.fromObject({ seconds: 90 }).as("milliseconds");

И затем используется как аргумент:

setTimeout(() => {}, ms);

Хотя это уже не календарная арифметика, а числовое представление, логика построена на одном объекте Duration как источнике данных.


Вложенные Duration в вычислениях

Duration может использоваться как часть более сложных вычислений:

const base = Duration.fromObject({ days: 1 });
const extra = Duration.fromObject({ hours: 5 });

const total = base.plus(extra);

После этого результат может быть применён:

DateTime.local().plus(total);

Такая модель позволяет строить многоуровневые временные выражения без потери структуры.


Совместимость Duration с объектами DateTime

При передаче Duration в методы DateTime происходит строгая типизация логики:

  • DateTime интерпретирует Duration как набор смещений;
  • Duration не модифицируется;
  • результат всегда новый экземпляр DateTime.
const dt = DateTime.local();

const shifted = dt.plus(
  Duration.fromObject({ months: 1, days: 10 })
);

Здесь месяцы и дни обрабатываются раздельно, что критично для календарной точности.


Использование Duration в параметризованных API

При проектировании API Duration часто применяется как универсальный аргумент:

function extendSubscription(user, period) {
  return {
    ...user,
    expiresAt: user.expiresAt.plus(period)
  };
}

В таком контексте Duration:

  • инкапсулирует бизнес-логику времени;
  • отделяет модель данных от арифметики;
  • обеспечивает единообразие операций.