Библиотека Luxon использует возможности стандарта Intl и
API интернационализации JavaScript для работы с различными календарными
системами. Это особенно важно при разработке международных приложений,
где даты должны отображаться в привычном для пользователя формате.
Под календарной системой понимается способ представления даты: структура месяцев, недель, лет и эпох. В большинстве приложений используется григорианский календарь, однако в ряде стран и культур применяются альтернативные системы:
Luxon не реализует календари самостоятельно — библиотека опирается на
Intl.DateTimeFormat, поэтому доступность конкретных
календарей зависит от среды выполнения и поддержки ICU.
Основной механизм выбора календарной системы — свойство
outputCalendar.
import { DateTime } from "luxon";
const date = DateTime.now().reconfigure({
outputCalendar: "islamic"
});
console.log(date.toLocaleString());
Метод reconfigure() создаёт новый объект
DateTime с изменёнными параметрами локализации.
Наиболее распространённые идентификаторы календарей:
| Календарь | Значение |
|---|---|
| Григорианский | gregory |
| Исламский | islamic |
| Буддийский | buddhist |
| Японский | japanese |
| Персидский | persian |
| Китайский | chinese |
| Еврейский | hebrew |
| Индийский | indian |
Исламский календарь основан на лунных циклах и содержит 12 лунных месяцев.
const date = DateTime.now().reconfigure({
locale: "ar",
outputCalendar: "islamic"
});
console.log(
date.toLocaleString(DateTime.DATE_FULL)
);
Пример результата:
١٢ رمضان ١٤٤٧ هـ
Некоторые среды выполнения поддерживают дополнительные разновидности:
outputCalendar: "islamic-umalqura"
или:
outputCalendar: "islamic-civil"
Поддержка зависит от реализации Intl.
Буддийский календарь широко используется в Таиланде. Основное отличие — смещение лет относительно григорианского календаря.
const date = DateTime.now().reconfigure({
locale: "th",
outputCalendar: "buddhist"
});
console.log(
date.toLocaleString(DateTime.DATE_FULL)
);
Пример:
24 พฤษภาคม 2569
Буддийский календарь опережает григорианский на 543 года.
const gregorian = DateTime.now();
const buddhist = gregorian.reconfigure({
outputCalendar: "buddhist"
});
console.log(gregorian.year);
console.log(buddhist.year);
Важно учитывать, что внутреннее хранение даты в Luxon остаётся неизменным. Меняется только отображение.
Японский календарь использует эпохи правления императоров.
const date = DateTime.now().reconfigure({
locale: "ja",
outputCalendar: "japanese"
});
console.log(
date.toLocaleString(DateTime.DATE_FULL)
);
Пример вывода:
令和8年5月24日
Каждая эпоха начинается с нового императора:
| Эпоха | Начало |
|---|---|
| Meiji | 1868 |
| Taisho | 1912 |
| Showa | 1926 |
| Heisei | 1989 |
| Reiwa | 2019 |
При форматировании Intl автоматически определяет текущую
эпоху.
Персидский календарь используется в Иране и Афганистане.
const date = DateTime.now().reconfigure({
locale: "fa",
outputCalendar: "persian"
});
console.log(
date.toLocaleString(DateTime.DATE_FULL)
);
Особенности:
Китайский календарь сочетает солнечные и лунные циклы.
const date = DateTime.now().reconfigure({
locale: "zh",
outputCalendar: "chinese"
});
console.log(
date.toLocaleString(DateTime.DATE_FULL)
);
Поддержка китайского календаря может различаться между браузерами и версиями Node.js.
Еврейский календарь применяется в религиозных и культурных системах Израиля.
const date = DateTime.now().reconfigure({
locale: "he",
outputCalendar: "hebrew"
});
console.log(
date.toLocaleString(DateTime.DATE_FULL)
);
Особенности:
Календарь и локаль — разные параметры.
const date = DateTime.now().reconfigure({
locale: "en",
outputCalendar: "persian"
});
В этом случае:
Результат может выглядеть так:
Ordibehesht 4, 1405 AP
Иногда календарь можно указать прямо в локали через Unicode Extension.
const date = DateTime.now().setLocale(
"th-TH-u-ca-buddhist"
);
console.log(
date.toLocaleString(DateTime.DATE_FULL)
);
Здесь:
u — Unicode extension;ca — calendar;buddhist — выбранный календарь.Luxon всегда хранит дату как абсолютный момент времени.
const now = DateTime.now();
При использовании альтернативного календаря меняется только визуальное представление.
const islamic = now.reconfigure({
outputCalendar: "islamic"
});
Это означает:
Получить активный календарь можно через
resolvedLocaleOptions().
const date = DateTime.now().reconfigure({
outputCalendar: "hebrew"
});
console.log(
date.resolvedLocaleOptions()
);
Результат:
{
locale: "en-US",
numberingSystem: "latn",
outputCalendar: "hebrew"
}
Календарные системы часто используются вместе с различными системами счисления.
const date = DateTime.now().reconfigure({
locale: "ar",
outputCalendar: "islamic",
numberingSystem: "arab"
});
console.log(
date.toLocaleString(DateTime.DATE_FULL)
);
| Система | Значение |
|---|---|
| Латинская | latn |
| Арабская | arab |
| Деванагари | deva |
| Тайская | thai |
Календари особенно полезны вместе с локализованным форматированием.
date.toLocaleString(DateTime.DATE_FULL);
date.toLocaleString(DateTime.DATETIME_FULL);
date.toLocaleString(DateTime.DATE_HUGE);
Пример:
const date = DateTime.now().reconfigure({
locale: "ja",
outputCalendar: "japanese"
});
console.log(
date.toLocaleString(DateTime.DATE_HUGE)
);
Метод toFormat() работает иначе.
date.toFormat("yyyy LLL dd");
Важно понимать, что toFormat() не всегда полностью
учитывает альтернативные календарные системы, поскольку использует
токены Luxon, а не Intl.DateTimeFormat.
Наиболее корректная локализация достигается через:
toLocaleString()
Поддержка календарей определяется:
Например, старые версии Node.js могут поддерживать только часть календарей.
Некоторые сборки Node.js используют минимальный ICU.
Проверка:
console.log(
Intl.supportedValuesOf("calendar")
);
Пример результата:
[
"gregory",
"buddhist",
"japanese",
"islamic"
]
Поддержка может отличаться:
| Браузер | Особенности |
|---|---|
| Chrome | Наиболее полная поддержка |
| Firefox | Хорошая совместимость |
| Safari | Возможны ограничения |
| Старые браузеры | Частичная поддержка |
Перед использованием календаря желательно проверять его наличие.
function supportsCalendar(calendar) {
return Intl.supportedValuesOf("calendar")
.includes(calendar);
}
console.log(
supportsCalendar("persian")
);
function formatDate(date, locale, calendar) {
return date
.reconfigure({
locale,
outputCalendar: calendar
})
.toLocaleString(DateTime.DATE_FULL);
}
Использование:
const now = DateTime.now();
console.log(
formatDate(now, "ar", "islamic")
);
console.log(
formatDate(now, "ja", "japanese")
);
console.log(
formatDate(now, "th", "buddhist")
);
Календарная система не влияет на timezone.
const date = DateTime.now()
.setZone("Asia/Almaty")
.reconfigure({
outputCalendar: "persian"
});
console.log(
date.toLocaleString(DateTime.DATETIME_FULL)
);
Здесь одновременно используются:
ISO-формат всегда остаётся григорианским.
const date = DateTime.now().reconfigure({
outputCalendar: "buddhist"
});
console.log(date.toISO());
Пример:
2026-05-24T14:20:00.000+06:00
Даже при использовании другого календаря toISO()
возвращает стандартную ISO-дату.
Luxon фактически выступает удобной оболочкой над
Intl.
Прямой аналог:
new Intl.DateTimeFormat("ja-JP-u-ca-japanese", {
dateStyle: "full"
}).format(new Date());
В Luxon:
DateTime.now()
.setLocale("ja-JP-u-ca-japanese")
.toLocaleString(DateTime.DATE_FULL);
Luxon предоставляет:
const users = [
{
locale: "en",
calendar: "gregory"
},
{
locale: "ar",
calendar: "islamic"
},
{
locale: "ja",
calendar: "japanese"
}
];
const now = DateTime.now();
for (const user of users) {
const formatted = now.reconfigure({
locale: user.locale,
outputCalendar: user.calendar
});
console.log(
formatted.toLocaleString(
DateTime.DATE_FULL
)
);
}
const date = DateTime.now()
.setLocale("fa")
.reconfigure({
outputCalendar: "persian"
});
Разделение локали и календаря делает код более читаемым.
Все операции создают новый экземпляр.
const original = DateTime.now();
const japanese = original.reconfigure({
outputCalendar: "japanese"
});
console.log(original === japanese);
Результат:
false
Исходный объект не изменяется.
const date = DateTime.now().reconfigure({
locale: "ar",
outputCalendar: "islamic",
numberingSystem: "arab",
weekSettings: {
firstDay: 6
}
});
Такая конфигурация позволяет адаптировать форматирование под региональные особенности.
Типичные сценарии:
toLocaleString()Для корректной локализации предпочтительнее:
toLocaleString()
а не:
toFormat()
Intl.supportedValuesOf("calendar")
Календарная система должна влиять только на отображение, а не на внутренние вычисления дат.
Одинаковый код может давать разные результаты: