Метод plus и minus

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

Каждый объект DateTime в Luxon является immutable. Это означает, что операция изменения времени не модифицирует исходный объект, а создаёт новый:

const { DateTime } = require("luxon");

const now = DateTime.now();
const later = now.plus({ days: 2 });

console.log(now.toISO());
console.log(later.toISO());

Исходный now остаётся неизменным, а later содержит новое значение. Это поведение одинаково для plus и minus.

Такой подход исключает побочные эффекты и делает цепочки вычислений предсказуемыми.

Метод plus: добавление временных интервалов

Метод plus используется для увеличения значения даты или времени на заданный интервал. Интервал задаётся объектом, где ключи представляют единицы времени.

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

Luxon поддерживает широкий набор единиц:

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

Базовое использование

const { DateTime } = require("luxon");

const date = DateTime.local(2024, 1, 1);
const result = date.plus({ days: 10 });

console.log(result.toISO()); 

Результат будет соответствовать 11 января 2024 года.

Комбинированные операции

В одном вызове можно комбинировать несколько единиц:

const start = DateTime.local(2024, 1, 1);

const result = start.plus({
  months: 1,
  days: 5,
  hours: 3
});

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

Метод minus: вычитание временных интервалов

Метод minus работает аналогично plus, но выполняет обратную операцию — уменьшение даты на заданный интервал.

Базовый пример

const { DateTime } = require("luxon");

const date = DateTime.local(2024, 1, 10);
const result = date.minus({ days: 5 });

console.log(result.toISO());

Результат будет соответствовать 5 января 2024 года.

Сложные интервалы

const base = DateTime.local(2024, 6, 15);

const result = base.minus({
  months: 2,
  weeks: 1,
  hours: 6
});

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

Особенности работы с месяцами и годами

Операции с месяцами и годами в Luxon не являются линейными из-за различий в длине месяцев и високосных годов.

const dt = DateTime.local(2024, 3, 31);

const shifted = dt.plus({ months: 1 });

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

Влияние порядка операций

Так как plus и minus возвращают новые объекты, их можно безопасно цепочечно комбинировать:

const { DateTime } = require("luxon");

const result = DateTime.local(2024, 1, 1)
  .plus({ days: 10 })
  .minus({ hours: 3 })
  .plus({ months: 2 });

Каждый шаг применяется к результату предыдущего вызова.

Работа с отрицательными значениями

Обе функции допускают отрицательные значения, что фактически инвертирует операцию:

const dt = DateTime.local(2024, 5, 10);

const result = dt.plus({ days: -5 });

Такой вызов эквивалентен minus({ days: 5 }), но использование явного minus считается более читаемым.

Взаимодействие с часовыми поясами

При использовании plus и minus с объектами DateTime, содержащими временную зону, Luxon корректно пересчитывает локальное время:

const dt = DateTime.fromISO("2024-03-10T10:00:00", { zone: "Europe/Paris" });

const shifted = dt.plus({ hours: 5 });

Если операция пересекает переход на летнее или зимнее время, Luxon автоматически учитывает сдвиги часового пояса.

Разница между duration и object-based arithmetic

Методы plus и minus принимают обычный объект, но внутри преобразуют его в Duration. Это важно при более точных вычислениях:

const result = DateTime.now().plus({ minutes: 90 });

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

Практические сценарии применения

Вычисление дедлайнов

const createdAt = DateTime.now();
const deadline = createdAt.plus({ days: 14 });

Откат состояния по времени

const snapshotTime = DateTime.now().minus({ hours: 6 });

Планирование периодических задач

function nextRun(lastRun) {
  return lastRun.plus({ days: 1, hours: 2 });
}

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

Luxon автоматически перераспределяет значения при превышении диапазонов:

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

const result = dt.plus({ minutes: 120 });

120 минут преобразуются в 2 часа, что делает результат консистентным.

Ограничения и особенности

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

Комбинация с форматированием

Часто результат арифметики сразу форматируется:

const result = DateTime.now()
  .plus({ days: 3 })
  .setLocale("ru")
  .toLocaleString(DateTime.DATE_FULL);

Такой подход используется для построения пользовательских интерфейсов, где требуется отображение будущих или прошлых дат без промежуточных переменных.