Каждый метод возвращает новый объект

Библиотека Luxon построена на строгом принципе неизменяемости объектов. Любая операция над датой, временем, длительностью или интервалом не модифицирует исходный экземпляр, а возвращает новый объект с применёнными изменениями.

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


Базовый принцип: отсутствие мутаций

Ключевая особенность всех объектов в Luxon заключается в том, что методы не изменяют внутреннее состояние экземпляра.

Любая операция вида:

  • добавление времени
  • изменение часового пояса
  • форматирование с преобразованием
  • нормализация даты

всегда возвращает новый объект.

Пример поведения DateTime

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 как цепочка преобразований

Объект 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 и создание новых экземпляров

Большинство методов 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 и неизменяемость

Объекты 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

Методы:

  • plus
  • minus
  • shiftTo
  • normalize

всегда возвращают новые значения.


Interval и производные изменения

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");

Отличие от мутабельных API

В ряде других библиотек даты могут изменяться “на месте”. В Luxon это исключено.

Сравнение концептуального поведения:

  • мутабельный подход: объект изменяется после вызова метода
  • 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");

Каждая переменная содержит самостоятельный объект, что позволяет анализировать процесс преобразования поэтапно.