Объект Date в JavaScript долгое время оставался
единственным встроенным инструментом для работы с датой и временем.
Несмотря на широкое распространение, у него накопилось множество
ограничений:
Luxon был создан как современная замена устаревшим подходам. Библиотека предоставляет выразительный, безопасный и предсказуемый API для работы со временем.
Объекты Luxon не изменяются после создания.
В стандартном Date многие методы мутируют объект:
const date = new Date();
date.setHours(15);
console.log(date);
В Luxon изменения создают новый экземпляр:
import { DateTime } from "luxon";
const now = DateTime.now();
const upd ated = now.se t({ hour: 15 });
console.log(now.toString());
console.log(updated.toString());
Это устраняет большое количество ошибок, связанных с неожиданным изменением состояния.
Date.parseПоведение стандартного парсинга отличается между браузерами.
new Date("01.02.2025");
Некоторые среды интерпретируют строку как:
Luxon требует явного формата.
const dt = DateTime.fromFormat(
"01.02.2025",
"dd.MM.yyyy"
);
console.log(dt.toISO());
Luxon позволяет безопасно проверять корректность данных.
const dt = DateTime.fromFormat(
"99.99.2025",
"dd.MM.yyyy"
);
console.log(dt.isValid);
console.log(dt.invalidReason);
Результат:
false
unit out of range
Стандартный Date хранит время в UTC, но отображает его в
локальном часовом поясе среды выполнения.
Это создаёт путаницу:
const date = new Date();
console.log(date);
console.log(date.toISOString());
Luxon делает работу с зонами явной.
const dt = DateTime.now().setZone("Europe/Moscow");
console.log(dt.toString());
const local = DateTime.now();
const tokyo = local.setZone("Asia/Tokyo");
console.log(local.toString());
console.log(tokyo.toString());
По умолчанию Luxon преобразует момент времени.
Иногда требуется сохранить локальные часы:
const dt = DateTime.fromISO(
"2025-05-10T12:00",
{ zone: "Europe/Moscow" }
);
const result = dt.setZone(
"Asia/Tokyo",
{ keepLocalTime: true }
);
console.log(result.toString());
const utc = DateTime.utc();
console.log(utc.toISO());
const local = DateTime.now();
const utc = local.toUTC();
console.log(local.toString());
console.log(utc.toString());
toLocaleStringСтандартное форматирование сложно читать и поддерживать.
date.toLocaleString("ru", {
year: "numeric",
month: "long",
day: "numeric"
});
Luxon предлагает компактный API.
const dt = DateTime.now();
console.log(
dt.toFormat("dd.MM.yyyy")
);
console.log(
dt.toFormat("HH:mm:ss")
);
| Токен | Значение |
|---|---|
| yyyy | год |
| MM | месяц |
| dd | день |
| HH | часы |
| mm | минуты |
| ss | секунды |
| cccc | день недели |
| LLLL | название месяца |
Пример:
const dt = DateTime.now();
console.log(
dt.toFormat("cccc, dd LLLL yyyy")
);
const dt = DateTime.now()
.setLocale("ru");
console.log(
dt.toFormat("cccc")
);
const dt = DateTime.now();
console.log(
dt.setLocale("en").toFormat("LLLL")
);
console.log(
dt.setLocale("fr").toFormat("LLLL")
);
console.log(
dt.setLocale("de").toFormat("LLLL")
);
const dt = DateTime.now();
const future = dt.plus({
days: 10,
hours: 5
});
console.log(future.toString());
const dt = DateTime.now();
const past = dt.minus({
weeks: 2
});
console.log(past.toString());
const dt = DateTime.now();
console.log(
dt.startOf("day").toString()
);
const dt = DateTime.now();
console.log(
dt.endOf("month").toString()
);
year
quarter
month
week
day
hour
minute
second
const a = DateTime.now();
const b = a.plus({ minutes: 1 });
console.log(a.equals(b));
console.log(a.toMillis());
console.log(b.toMillis());
console.log(a < b);
IntervalLuxon содержит встроенный тип интервалов.
import { Interval } from "luxon";
const start = DateTime.now();
const end = start.plus({ days: 5 });
const interval = Interval.fromDateTimes(
start,
end
);
console.log(interval.length("days"));
const now = DateTime.now();
console.log(
interval.contains(now)
);
const a = Interval.fromDateTimes(
DateTime.now(),
DateTime.now().plus({ days: 10 })
);
const b = Interval.fromDateTimes(
DateTime.now().plus({ days: 5 }),
DateTime.now().plus({ days: 15 })
);
console.log(a.overlaps(b));
DurationLuxon умеет работать не только с моментами времени, но и с продолжительностями.
import { Duration } from "luxon";
const duration = Duration.fromObject({
hours: 2,
minutes: 30
});
console.log(duration.toISO());
const duration = Duration.fromObject({
minutes: 150
});
console.log(
duration.as("hours")
);
const duration = Duration.fromObject({
minutes: 90
}).normalize();
console.log(duration.toObject());
Результат:
{
hours: 1,
minutes: 30
}
diffconst start = DateTime.now();
const end = start.plus({
days: 3,
hours: 5
});
const diff = end.diff(start, [
"days",
"hours"
]);
console.log(diff.toObject());
const diff = end.diff(start);
console.log(diff.toMillis());
Luxon ориентирован на ISO 8601.
Пример ISO-строки:
2025-05-10T14:30:00.000+03:00
const dt = DateTime.fromISO(
"2025-05-10T14:30:00"
);
console.log(dt.toString());
const dt = DateTime.now();
console.log(dt.toISO());
const dt = DateTime.fromRFC2822(
"Tue, 25 Nov 2025 13:30:00 +0300"
);
console.log(dt.toISO());
const dt = DateTime.fromHTTP(
"Sun, 06 Nov 1994 08:49:37 GMT"
);
console.log(dt.toISO());
const dt = DateTime.fromSeconds(
1700000000
);
console.log(dt.toISO());
const dt = DateTime.fromMillis(
1700000000000
);
console.log(dt.toISO());
const dt = DateTime.now();
console.log(dt.toSeconds());
console.log(dt.toMillis());
const dt = DateTime.now();
console.log(dt.weekday);
console.log(dt.weekNumber);
console.log(dt.ordinal);
console.log(
DateTime.now().isInLeapYear
);
const dates = [
DateTime.now(),
DateTime.now().minus({ days: 2 }),
DateTime.now().plus({ days: 1 })
];
dates.sort(
(a, b) => a.toMillis() - b.toMillis()
);
console.log(dates);
const start = DateTime.now();
const end = start.plus({ days: 5 });
const interval = Interval.fromDateTimes(
start,
end
);
const days = interval.splitBy({
days: 1
});
console.log(days);
const dt = DateTime.now();
console.log(
JSON.stringify(dt)
);
const json = dt.toJSON();
const restored = DateTime.fromISO(json);
console.log(restored.toString());
TZ=Europe/Moscow node app.js
import { Settings } from "luxon";
Settings.defaultZone = "UTC";
Settings.defaultLocale = "ru";
Luxon активно использует Intl.
Проверка:
console.log(
typeof Intl !== "undefined"
);
const dt = DateTime.now().setZone(
"Mars/Base"
);
console.log(dt.isValid);
console.log(dt.invalidReason);
console.log(dt.invalidExplanation);
function log(message) {
const timestamp = DateTime.now()
.toFormat("yyyy-MM-dd HH:mm:ss");
console.log(
`[${timestamp}] ${message}`
);
}
log("Server started");
const deadline = DateTime.fromISO(
"2025-12-31"
);
const now = DateTime.now();
const diff = deadline.diff(now, [
"days",
"hours"
]);
console.log(diff.toObject());
const expiresAt = DateTime.fromISO(
"2025-01-01"
);
const expired =
DateTime.now() > expiresAt;
console.log(expired);
const events = [
{
title: "Meeting",
date: DateTime.fromISO(
"2025-06-10T12:00"
)
},
{
title: "Conference",
date: DateTime.fromISO(
"2025-06-15T09:00"
)
}
];
events.forEach(event => {
console.log(
event.title,
event.date.toFormat(
"dd.MM.yyyy HH:mm"
)
);
});
IntlВ старых окружениях возможны проблемы:
Luxon крупнее минималистичных решений вроде:
Luxon использует возможности среды выполнения.
Качество поддержки зон зависит от: