Календарная система в ECMAScript Internationalization API
определяется через Unicode Locale Identifier и параметр
calendar, который влияет на то, как формируются и
интерпретируются даты в локализованных форматах. В основе лежит стандарт
Unicode CLDR, где каждая календарная система имеет строковый
идентификатор и может быть выбрана как часть языкового тега.
В спецификации Intl календарь не является отдельной сущностью уровня
приложения — он встроен в локаль через расширение Unicode
-u-ca-.
Структура тега локали:
language[-script][-region]-u-ca-calendar
Пример:
const locale = "ar-EG-u-ca-islamic";
Здесь:
ar-EG — арабский язык, Египетu-ca-islamic — исламский календарьЭто расширение влияет на поведение всех API, работающих с датами.
В Intl используются стандартизированные строки календарных систем. Они соответствуют Unicode CLDR:
gregory — григорианский календарь (де-факто
стандарт)buddhist — буддийский календарь (используется в
Таиланде)chinese — китайский лунно-солнечный календарьcoptic — коптский календарьethiopic — эфиопский календарьhebrew — еврейский календарьindian — индийский национальный календарьislamic — исламский (лунный) календарьislamic-umalqura — модифицированный исламский календарь
(Умм аль-Кура)iso8601 — ISO календарная системаjapanese — японский календарь эпохpersian — персидский календарьroc — календарь Республики КитайЭти значения используются как в параметрах API, так и в расширениях локали.
Календарная система задаётся через опцию calendar:
const fmt = new Intl.DateTimeFormat("en-US", {
calendar: "islamic"
});
console.log(fmt.format(new Date()));
Форматирование даты остаётся локализованным, но система отсчёта лет и месяцев изменяется в соответствии с выбранным календарём.
При этом сам язык форматирования (например, названия месяцев)
определяется локалью "en-US", а не календарём.
Разные календарные системы могут радикально менять числовые значения года:
const d = new Date(2026, 0, 1);
console.log(new Intl.DateTimeFormat("en-US", {
calendar: "gregory",
year: "numeric",
month: "long",
day: "numeric"
}).format(d));
console.log(new Intl.DateTimeFormat("en-US", {
calendar: "islamic",
year: "numeric",
month: "long",
day: "numeric"
}).format(d));
В первом случае используется привычный год 2026, во втором — другой календарный отсчёт, соответствующий исламской системе летоисчисления.
ca в строке локалиКалендарь можно задать не только через
Intl.DateTimeFormat, но и через саму локаль:
const dtf = new Intl.DateTimeFormat("th-TH-u-ca-buddhist", {
year: "numeric",
month: "long",
day: "numeric"
});
Здесь:
th-TH — тайский язык и регионu-ca-buddhist — буддийский календарьЭтот способ считается более декларативным, поскольку календарь становится частью идентификатора локали, а не параметром форматирования.
Объект Intl.Locale предоставляет структурированный
доступ к компонентам локали, включая календарь.
const loc = new Intl.Locale("ja-JP-u-ca-japanese");
console.log(loc.calendar); // "japanese"
Можно также программно формировать локаль:
const loc = new Intl.Locale("en-US", {
calendar: "hebrew"
});
console.log(loc.toString());
Результирующая локаль будет содержать расширение
-u-ca-hebrew.
Современные реализации ECMAScript предоставляют метод:
Intl.supportedValuesOf("calendar");
Он возвращает список календарных систем, поддерживаемых окружением:
[
"buddhist",
"chinese",
"coptic",
"dangi",
"ethiopic",
"gregory",
"hebrew",
"indian",
"islamic",
"islamic-civil",
"islamic-rgsa",
"islamic-tbla",
"islamic-umalqura",
"iso8601",
"japanese",
"persian",
"roc"
]
Наличие конкретных значений зависит от реализации движка JavaScript и данных ICU.
Важно различать:
Date в JavaScript всегда хранит время в виде Unix
timestamp (миллисекунды от эпохи Unix)Это означает, что:
const d = new Date("2026-05-01T00:00:00Z");
не меняется при смене календаря. Меняется только интерпретация при выводе.
Некоторые календари вводят дополнительные элементы, не существующие в григорианской системе:
japanese)Использует эпохи правления императоров:
new Intl.DateTimeFormat("ja-JP", {
calendar: "japanese",
year: "numeric",
era: "short",
month: "numeric",
day: "numeric"
}).format(new Date());
Вывод может включать обозначение эпохи вроде Reiwa.
chinese)Может включать циклы и лунные элементы, но в Intl обычно сводится к году и месяцу по лунно-солнечной системе.
Если календарь не соответствует культурной локали, Intl не выдаёт ошибку. Вместо этого:
Пример:
new Intl.DateTimeFormat("fr-FR", {
calendar: "islamic"
});
Французский язык остаётся французским, но календарная система меняется.
Календарь влияет на:
year)month)era)Но не влияет напрямую на:
hour, minute,
second)timeZone)Пример комбинированного использования:
new Intl.DateTimeFormat("en-US", {
calendar: "persian",
timeZone: "Asia/Tehran",
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit"
});
Здесь календарь определяет систему летоисчисления, а часовой пояс — смещение времени.
Реализация календарей в JavaScript опирается на библиотеку ICU (International Components for Unicode). Именно ICU определяет:
Поэтому различия между окружениями (Node.js, браузеры) возможны при устаревших версиях ICU.
Календарь не влияет на:
Date объектовconst a = new Date("2026-01-01");
const b = new Date("2026-12-31");
console.log(a < b); // true
Эти операции всегда выполняются в универсальном времени, независимо от календаря.
Календарные системы в Intl используются в основном для:
При этом внутренняя логика приложений почти всегда остаётся на григорианской системе, а альтернативные календари применяются только на уровне представления данных.