Переход с Day.js на Luxon начинается с понимания фундаментального
различия архитектур. Day.js ориентирован на минималистичную обёртку над
Date с плагинами, тогда как Luxon строит собственную модель
времени поверх международного стандарта ICU и нативной поддержки
Intl.
Ключевой сдвиг:
DateDateTime,
Duration, IntervalЭто приводит к изменению подхода к работе со временем: вместо цепочек плагинов используется единая, строго типизированная модель.
import dayjs from "dayjs";
const d = dayjs();
const fromString = dayjs("2026-01-01");
import { DateTime } from "luxon";
const dt = DateTime.now();
const fromString = DateTime.fromISO("2026-01-01");
Luxon не парсит строки произвольно. Требуется явно указать формат:
DateTime.fromFormat("01-01-2026", "dd-MM-yyyy");
dayjs().format("YYYY-MM-DD HH:mm");
DateTime.now().toFormat("yyyy-MM-dd HH:mm");
YYYY → yyyyDD → ddHH:mm остаётся аналогичнымLuxon использует форматирование, близкое к Unicode Date Format Patterns.
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs().tz("Europe/Paris");
DateTime.now().setZone("Europe/Paris");
DateTime.utc();
Luxon не требует подключения плагинов для базовой работы с зонами времени.
Обе библиотеки используют иммутабельные объекты, но Luxon делает это более строго.
const d = dayjs();
const updated = d.add(2, "day");
const dt = DateTime.now();
const updated = dt.plus({ days: 2 });
dayjs().add(3, "hour").subtract(10, "minute");
DateTime.now()
.plus({ hours: 3 })
.minus({ minutes: 10 });
Luxon исключает строковые единицы измерения, снижая риск ошибок.
Day.js использует плагин duration, тогда как Luxon имеет
встроенную модель.
import { Duration } from "luxon";
const dur = Duration.fromObject({ hours: 2, minutes: 30 });
dur.as("minutes"); // 150
dayjs.duration(150, "minutes");
В Day.js отсутствует полноценный аналог.
import { Interval, DateTime } from "luxon";
const start = DateTime.now();
const end = start.plus({ days: 5 });
const interval = Interval.fromDateTimes(start, end);
interval.contains(DateTime.now());
import "dayjs/locale/ru";
dayjs.locale("ru");
DateTime.now().setLocale("ru");
Luxon опирается на Intl, поэтому поддержка локалей более
системная и зависит от окружения.
import relativeTime from "dayjs/plugin/relativeTime";
dayjs.extend(relativeTime);
dayjs().fromNow();
DateTime.now().toRelative();
или с базовой точкой:
DateTime.now().toRelative({ base: DateTime.now().minus({ hours: 5 }) });
Day.js допускает гибкое поведение:
dayjs("2026/01/01");
Luxon требует явности:
DateTime.fromFormat("2026/01/01", "yyyy/MM/dd");
Также доступны варианты:
DateTime.fromISO("2026-01-01");
DateTime.fromJSDate(new Date());
DateTime.fromMillis(1700000000000);
dayjs(1700000000000);
DateTime.fromMillis(1700000000000);
И обратно:
dt.toMillis();
dayjs("invalid").isValid();
DateTime.fromISO("invalid").isValid;
Разница:
Day.js требует подключений:
Luxon включает всё в ядро:
Day.js:
dayjs().startOf("day");
dayjs().endOf("day");
Luxon:
DateTime.now().startOf("day");
DateTime.now().endOf("day");
Day.js:
dayjs(a).isBefore(b);
dayjs(a).isAfter(b);
Luxon:
a < b;
a > b;
или:
a < b; // сравнение DateTime через valueOf
Код с неявным парсингом требует переработки:
Day.js:
dayjs(userInput);
Luxon:
DateTime.fromISO(userInput);
// или fromFormat / fromJSDate
Day.js:
add(1, "month");
Luxon:
plus({ months: 1 });
| Day.js plugin | Luxon аналог |
|---|---|
| utc | встроено |
| timezone | setZone |
| duration | Duration |
| relativeTime | toRelative |
| isSameOrAfter | сравнение оператором |
dayjs(new Date());
DateTime.fromJSDate(new Date());
Обратное преобразование:
dt.toJSDate();
dt.toISO();
dt.toISODate();
dt.toISOTime();
dt.toRFC2822();
Day.js требует форматирования вручную через
.format().
Luxon предоставляет более строгую модель ошибок:
const dt = DateTime.fromFormat("2026-99-99", "yyyy-MM-dd");
dt.isValid; // false
dt.invalidReason;
dt.invalidExplanation;
Day.js ограничивается булевым флагом.
Day.js допускает некорректные входные данные, Luxon — нет.
Синтаксис форматирования полностью отличается.
Код с .extend() требует удаления и замены на встроенные
API.
Luxon требует явного управления через setZone.
Часто используется смешанный подход:
import dayjs from "dayjs";
import { DateTime } from "luxon";
const legacy = dayjs(date);
const modern = DateTime.fromJSDate(legacy.toDate());
Обратная конверсия:
const d = DateTime.now().toJSDate();
dayjs(d);
| Концепция | Day.js | Luxon |
|---|---|---|
| Основной объект | dayjs() | DateTime |
| Длительность | plugin | Duration |
| Интервал | отсутствует | Interval |
| Часовые пояса | plugin | setZone |
| Форматирование | format() | toFormat() |
| Парсинг | нестрогий | строгий |
| Локали | plugin | setLocale |
Day.js ориентирует разработку на «удобство по умолчанию», Luxon — на «явность и контроль». Это отражается во всех аспектах:
Переход требует пересмотра привычных сокращений в пользу более детальной и предсказуемой модели работы со временем.