В библиотеке Luxon центральная идея API строится вокруг неизменяемых объектов даты и времени, где каждое преобразование возвращает новый экземпляр, а не модифицирует существующий. Это фундаментально отличает её от встроенного объекта Date и от более ранних подходов, использовавшихся в экосистеме JavaScript для работы со временем.
Встроенный Date в JavaScript является изменяемым
объектом, но его поведение не всегда очевидно: методы вроде
setDate, setHours, setMonth
изменяют состояние объекта напрямую. Luxon полностью отказывается от
такого подхода.
Каждая операция в Luxon возвращает новый объект:
const { DateTime } = require('luxon');
const dt1 = DateTime.now();
const dt2 = dt1.plus({ days: 1 });
console.log(dt1.toISO());
console.log(dt2.toISO());
Здесь dt1 остаётся неизменным, а dt2
представляет новое значение. Это делает API предсказуемым и снижает
количество побочных эффектов в приложениях.
В отличие от Date, где используется
new Date(), Luxon почти полностью избегает прямого
использования конструктора. Основной способ создания объектов —
статические методы:
DateTime.now()DateTime.local()DateTime.utc()DateTime.fromISO()DateTime.fromMillis()DateTime.fromObject()Такой подход делает намерение кода явным:
const a = DateTime.now();
const b = DateTime.utc(2026, 1, 1);
const c = DateTime.fromISO('2026-05-23T10:00:00');
В сравнении с new Date("..."), где строка может
интерпретироваться по-разному в разных средах, Luxon делает различие
между форматами входных данных строгим и прозрачным.
Одно из ключевых отличий Luxon от стандартного Date —
полноценная модель временных зон. Встроенный Date всегда
хранит время в UTC, но предоставляет локальное представление через
системные настройки, что часто приводит к путанице.
Luxon вводит явное управление зонами через API:
const dt = DateTime.now().setZone('Europe/Berlin');
const utc = DateTime.utc();
const local = DateTime.local();
Каждый объект содержит информацию о зоне, и преобразование между ними выполняется явно:
const ny = dt.setZone('America/New_York');
Это убирает неявные преобразования, характерные для
Date.
Moment.js исторически использовал изменяемый API:
moment().add(1, 'day').subtract(2, 'hours');
Хотя цепочки методов выглядят удобно, они опираются на мутацию исходного объекта. Luxon сохраняет цепочечный стиль, но делает его функциональным:
const dt = DateTime.now()
.plus({ days: 1 })
.minus({ hours: 2 });
Каждый шаг возвращает новый экземпляр, что позволяет безопасно использовать объекты в асинхронном коде, Redux-подобных структурах и кэшировании.
В отличие от Date, который пытается охватить все аспекты
времени, Luxon разделяет модель на три сущности:
DateTime — конкретный момент времениDuration — длительностьInterval — промежуток между двумя моментамиТакое разделение радикально меняет API:
const start = DateTime.local(2026, 1, 1);
const end = DateTime.local(2026, 2, 1);
const interval = Interval.fromDateTimes(start, end);
const duration = interval.toDuration();
В стандартном Date подобная семантика отсутствует и
обычно реализуется вручную через арифметику миллисекунд.
Moment.js широко использовал строковые шаблоны формата:
moment().format("YYYY-MM-DD HH:mm");
Luxon разделяет форматирование на два подхода:
toFormat() — гибкие кастомные форматыtoLocaleString() — локализованные форматы через Intl
APIdt.toFormat('yyyy LLL dd');
dt.toLocaleString(DateTime.DATETIME_MED);
Это отличие важно: Luxon делает акцент на стандартах ECMAScript Internationalization API, а не на собственных строковых интерпретаторах.
Встроенный Date допускает неявный парсинг строк, который
зависит от движка:
new Date("2026-05-23 10:00")
Luxon требует явного указания формата:
DateTime.fromISO("2026-05-23T10:00:00");
DateTime.fromFormat("23-05-2026", "dd-MM-yyyy");
Если формат не совпадает, объект становится невалидным, что можно проверить:
const dt = DateTime.fromISO("invalid");
console.log(dt.isValid);
Такой подход устраняет скрытые ошибки парсинга.
В отличие от многих библиотек прошлого поколения, Luxon избегает перегруженных конструкторов. Вместо одного универсального входа используется набор специализированных методов:
fromISOfromRFC2822fromSeconds,
fromMillisfromObjectЭто уменьшает неоднозначность API и делает код более читаемым.
Luxon опирается на встроенный Intl API, что меняет
подход к локализации по сравнению с Moment.js.
dt.setLocale('ru').toLocaleString(DateTime.DATE_FULL);
Вместо ручных таблиц локалей используется системный механизм JavaScript, что снижает размер библиотеки и повышает совместимость с современными браузерами.
В Date арифметика выполняется через миллисекунды:
const d = new Date();
d.setTime(d.getTime() + 86400000);
В Luxon используются семантические единицы:
dt.plus({ days: 1 });
dt.minus({ weeks: 2, hours: 3 });
Это делает код ближе к предметной области и исключает необходимость ручного пересчёта миллисекунд.
Встроенный Date использует методы типа
getFullYear(), getMonth(). Luxon использует
свойства через геттеры:
dt.year
dt.month
dt.day
dt.hour
Это делает API более компактным и читаемым, убирая избыточность вызовов функций.
Moment.js часто полагался на глобальное состояние:
moment.locale('ru');
Luxon избегает глобальных эффектов. Все настройки привязаны к конкретному экземпляру:
dt.setLocale('ru');
dt.setZone('Europe/Moscow');
Это делает поведение объектов изолированным и предсказуемым в многомодульных приложениях.
В Luxon UTC рассматривается как базовая координата, но не
навязывается как единственное представление. В отличие от
Date, где UTC скрыт за локальными преобразованиями, Luxon
позволяет явно переключаться:
DateTime.utc(2026, 5, 23);
dt.toUTC();
dt.toLocal();
Каждое преобразование создаёт новый объект с новой семантикой времени, а не изменяет внутреннее состояние.
Встроенный Date при сериализации автоматически
превращается в строку ISO:
JSON.stringify(new Date());
Luxon требует явного контроля:
dt.toISO();
dt.toJSON();
Это исключает неожиданные форматы при передаче данных между сервисами.
Несмотря на функциональную природу, Luxon сохраняет цепочечный стиль, но делает его строго детерминированным:
DateTime.now()
.setZone('UTC')
.plus({ days: 2 })
.setLocale('en')
.toFormat('yyyy-MM-dd');
Каждый метод возвращает новый объект с чётко определённым состоянием, без скрытых побочных эффектов и мутаций исходного значения.