Библиотека Luxon построена на строгом принципе неизменяемости объектов. Любая операция над датой, временем, длительностью или интервалом не модифицирует исходный экземпляр, а возвращает новый объект с применёнными изменениями.
Такой подход устраняет класс целого ряда ошибок, связанных с непредсказуемым изменением состояния, и делает работу с датами более функциональной по стилю: каждый шаг преобразования создаёт новую сущность, сохраняя предыдущую неизменной.
Ключевая особенность всех объектов в Luxon заключается в том, что методы не изменяют внутреннее состояние экземпляра.
Любая операция вида:
всегда возвращает новый объект.
import { DateTime } from "luxon";
const dt1 = DateTime.local(2026, 1, 1);
const dt2 = dt1.plus({ days: 5 });
console.log(dt1.toISO()); // 2026-01-01T00:00:00.000
console.log(dt2.toISO()); // 2026-01-06T00:00:00.000
Исходный dt1 остаётся неизменным. Метод
plus создаёт новый экземпляр DateTime.
Объект DateTime в Luxon часто используется в цепочках
вызовов. Каждый метод добавляет трансформацию и возвращает новый объект,
позволяя строить выразительные последовательности операций.
import { DateTime } from "luxon";
const result = DateTime.local(2026, 5, 23)
.plus({ days: 10 })
.setZone("UTC")
.minus({ hours: 3 })
.setLocale("ru");
console.log(result.toString());
Каждый шаг создаёт отдельный экземпляр, не затрагивая предыдущий.
Большинство методов DateTime возвращают новый объект. К
ним относятся:
plus()minus()Обе операции создают новую дату на основе исходной.
const base = DateTime.local();
const future = base.plus({ months: 2 });
const past = base.minus({ weeks: 1 });
Методы настройки также не мутируют объект:
set()reconfigure()const dt = DateTime.local(2026, 5, 23);
const upd ated = dt.se t({ hour: 10, minute: 30 });
dt остаётся без изменений.
const dt = DateTime.local();
const ny = dt.setZone("America/New_York");
const tokyo = dt.setZone("Asia/Tokyo");
Каждый вызов создаёт новый экземпляр с пересчитанным временем.
Объекты Duration в Luxon также иммутабельны. Любое
изменение длительности приводит к созданию нового экземпляра.
import { Duration } from "luxon";
const d1 = Duration.fromObject({ hours: 2 });
const d2 = d1.plus({ minutes: 30 });
console.log(d1.toISO()); // PT2H
console.log(d2.toISO()); // PT2H30M
Методы:
plusminusshiftTonormalizeвсегда возвращают новые значения.
Interval представляет диапазон времени и также следует
принципу неизменяемости.
import { DateTime, Interval } from "luxon";
const start = DateTime.local(2026, 1, 1);
const end = DateTime.local(2026, 1, 10);
const i1 = Interval.fromDateTimes(start, end);
const i2 = i1.set({ end: end.plus({ days: 5 }) });
i1 сохраняется в исходном виде, i2 — новый
диапазон.
Даже операции форматирования могут возвращать новые сущности или промежуточные представления, не влияя на исходные данные.
const dt = DateTime.local(2026, 5, 23);
const iso = dt.toISO();
const formatted = dt.toFormat("dd.MM.yyyy");
Хотя здесь возвращаются строки, сам объект dt остаётся
неизменным.
Иммутабельность в Luxon влияет на архитектуру кода:
Каждый метод гарантированно не изменяет входные данные, что упрощает трассировку состояния.
Один и тот же объект можно использовать в нескольких вычислениях без риска побочных эффектов.
const base = DateTime.local();
const a = base.plus({ days: 1 });
const b = base.plus({ days: 2 });
Функциональный стиль становится естественным:
const result = DateTime.local()
.startOf("day")
.plus({ hours: 6 })
.setZone("UTC");
В ряде других библиотек даты могут изменяться “на месте”. В Luxon это исключено.
Сравнение концептуального поведения:
Это исключает случайное изменение состояния, особенно в асинхронных сценариях и при передаче объектов между модулями.
Иммутабельность делает цепочки основным способом работы с датами и временем.
const invoiceDue = DateTime.local()
.plus({ days: 30 })
.set({ hour: 23, minute: 59, second: 59 })
.toUTC();
Каждый вызов — отдельное преобразование, формирующее новый объект, что позволяет точно контролировать каждое изменение.
Использование неизменяемых объектов в Luxon приводит к упрощению состояния в приложении:
Особенно это заметно в сложных системах планирования, календарях и финансовых расчётах, где одна ошибка в изменении даты может привести к каскадным последствиям.
Каждый шаг преобразования можно сохранять отдельно, формируя промежуточные состояния:
const base = DateTime.local(2026, 5, 23);
const step1 = base.plus({ days: 7 });
const step2 = step1.setZone("UTC");
const step3 = step2.startOf("day");
Каждая переменная содержит самостоятельный объект, что позволяет анализировать процесс преобразования поэтапно.