Работа с датой и временем долгое время оставалась одной из самых
неудобных областей языка JavaScript. Встроенный объект
Date, появившийся ещё в ранних версиях ECMAScript,
обеспечивал базовые возможности, однако имел множество архитектурных
недостатков:
Пример типичной проблемы встроенного Date:
const date = new Date('2024-05-01');
console.log(date);
Результат зависит от окружения, часового пояса и браузера. В разных системах интерпретация строки может отличаться.
Даже простые операции выглядели громоздко:
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1;
const day = now.getDate();
Отдельную сложность представляла изменяемость объекта:
const date = new Date();
date.setMonth(11);
date.setDate(25);
Каждый вызов изменял исходный объект, что часто приводило к трудноуловимым ошибкам.
На фоне этих ограничений экосистема JavaScript постепенно начала создавать специализированные библиотеки для работы с датами.
В 2011 году появилась библиотека Moment.js, быстро ставшая фактическим стандартом работы с датами в JavaScript.
Moment.js решал множество проблем:
Пример использования:
const date = moment();
console.log(date.format('YYYY-MM-DD'));
Добавление времени выглядело значительно проще:
const result = moment()
.add(7, 'days')
.subtract(2, 'hours');
console.log(result.format());
Moment.js оказал огромное влияние на JavaScript-разработку:
Однако со временем начали проявляться серьёзные архитектурные ограничения.
Moment.js использовал mutable-подход.
const date = moment();
const updated = date.add(1, 'day');
console.log(date === updated); // true
Исходный объект изменялся напрямую.
В крупных приложениях это приводило к:
Moment.js создавался в эпоху, когда размер JavaScript-бандла ещё не был критически важным фактором.
Со временем ситуация изменилась:
Moment.js плохо поддавался оптимизации:
К моменту активного распространения:
Moment.js оставался продуктом более ранней эпохи JavaScript.
Команда Moment.js официально объявила библиотеку legacy-проектом.
Разработка новых возможностей практически прекратилась. Основной фокус сместился на:
Это стало важным сигналом для всей экосистемы.
После доминирования Moment.js начали активно развиваться альтернативы:
Каждая библиотека пыталась решить проблемы Moment.js своим способом.
Luxon был разработан Исааком Каммароном — одним из участников команды Moment.js.
Главная идея проекта заключалась не просто в создании очередной date-библиотеки, а в переосмыслении самого подхода к работе со временем в JavaScript.
Luxon появился как попытка:
Библиотека была впервые представлена в 2017 году.
Все объекты в Luxon неизменяемы.
const date = DateTime.now();
const updated = date.plus({ days: 1 });
console.log(date === updated); // false
Методы возвращают новый объект вместо изменения существующего.
Преимущества:
Одним из важнейших отличий Luxon стало активное использование
встроенного международного API JavaScript — Intl.
Это позволило:
Пример:
DateTime.now().setLocale('fr').toLocaleString();
Luxon делегирует локализацию движку JavaScript, а не реализует её самостоятельно.
Luxon строился уже в эпоху ES6+.
В библиотеке активно используются:
Пример:
DateTime.now()
.setZone('Europe/Paris')
.plus({ days: 3 })
.startOf('day');
Такой код значительно проще читать по сравнению с классическим API
Date.
Luxon строится вокруг нескольких ключевых классов.
Главный объект библиотеки.
Представляет:
const dt = DateTime.now();
Используется для представления временных промежутков.
const duration = Duration.fromObject({
hours: 2,
minutes: 30
});
Позволяет работать с временными интервалами.
const interval = Interval.fromDateTimes(start, end);
Работа с timezone всегда считалась одной из самых сложных задач в программировании.
Luxon значительно упростил этот процесс.
Пример:
const date = DateTime.now()
.setZone('Asia/Tokyo');
console.log(date.toString());
Библиотека использует возможности Intl и IANA timezone
database, встроенные в среду выполнения.
В Moment.js для этого требовались дополнительные расширения:
moment.tz('2024-05-01', 'Asia/Tokyo');
В Luxon поддержка временных зон встроена изначально.
Luxon поддерживает несколько уровней форматирования.
DateTime.now().toISO();
DateTime.now().toLocaleString(DateTime.DATE_FULL);
DateTime.now().toFormat('dd.MM.yyyy');
API получился одновременно:
Luxon быстро занял важное место в современном JavaScript-стеке.
Особенно активно библиотека используется:
Причины популярности:
| Возможность | Moment.js | Luxon |
|---|---|---|
| Immutable API | Нет | Да |
| Intl API | Практически не используется | Активно используется |
| Tree shaking | Плохой | Лучше |
| Архитектура | Устаревшая | Современная |
| Поддержка timezone | Через плагины | Встроенная |
| Размер | Большой | Меньше |
| Статус | Legacy | Активно используется |
date-fns использует функциональный подход.
Пример:
import { addDays } from 'date-fns';
const result = addDays(new Date(), 5);
Luxon, напротив, строится вокруг объектной модели:
DateTime.now().plus({ days: 5 });
Разница философий:
Day.js создавался как максимально лёгкая альтернатива Moment.js.
API Day.js почти полностью повторяет Moment.js:
dayjs().add(1, 'day');
Преимущества Day.js:
Однако Luxon предлагает:
Duration и
Interval.Сообщество JavaScript постепенно пришло к пониманию, что проблема
лежит глубже библиотек — сам встроенный Date требует
замены.
Так появился проект Temporal.
Temporal разрабатывается как новый стандарт ECMAScript для работы с датой и временем.
Многие идеи Temporal перекликаются с Luxon:
В определённом смысле Luxon стал промежуточным этапом между эпохой Moment.js и будущим стандартом Temporal.
Luxon строится вокруг нескольких фундаментальных принципов.
Библиотека старается избегать неоднозначностей:
DateTime.fromISO('2024-05-01');
Метод явно показывает формат входных данных.
DateTime.now()
.setZone('UTC')
.plus({ hours: 5 })
.endOf('day');
Код читается почти как описание последовательности действий.
Immutable-подход уменьшает количество ошибок:
const original = DateTime.now();
const modified = original.plus({ days: 1 });
console.log(original.toISO());
console.log(modified.toISO());
Исходное значение гарантированно сохраняется.
Распространение Luxon связано сразу с несколькими факторами.
Экосистема нуждалась в современной замене.
Timezone и локализация стали критически важными:
После распространения:
immutable-архитектура стала восприниматься как стандарт хорошего дизайна.
Современные движки получили мощную поддержку:
Intl;Luxon смог опереться на эти возможности и отказаться от многих внутренних механизмов.
Несмотря на преимущества, Luxon не стал универсальным решением для всех задач.
В старых окружениях поддержка может быть ограниченной.
Иногда требуются polyfill-решения.
Хотя Luxon меньше Moment.js, он тяжелее ultra-light библиотек.
Luxon остаётся библиотекой поверх существующих возможностей JavaScript, а не частью языка.
Сегодня Luxon занимает нишу между:
Библиотека особенно хорошо подходит для:
Luxon стал важным этапом эволюции JavaScript-инструментов для работы со временем, показав, каким может быть современный API даты и времени: