Календарные системы

Календарная система в контексте ECMAScript Internationalization API определяет правила интерпретации дат: как разбиваются годы, месяцы, дни, какие используются эпохи и какие исторические или религиозные системы летоисчисления применяются. Встроенная локализация JavaScript опирается на ICU (International Components for Unicode), где календарь является частью расширенных параметров локали.

Календарь влияет не на хранение времени в JavaScript (оно всегда основано на Unix time — миллисекундах с эпохи 1970-01-01 UTC), а на представление даты.


Базовая модель календарей в Intl

В Intl.DateTimeFormat календарь задаётся через расширение локали или через параметр calendar.

Пример логики:

  • внутреннее время: timestamp
  • календарь: способ разложения timestamp на год/месяц/день
  • локаль: правила форматирования чисел, порядка полей, языка

Календарь — это часть Unicode Locale Identifier:

en-US-u-ca-gregory
ar-SA-u-ca-islamic
ja-JP-u-ca-japanese

Здесь ca (calendar) — ключ расширения Unicode.


Основной календарь: Gregorian

Большинство локалей по умолчанию используют григорианский календарь (gregory).

const fmt = new Intl.DateTimeFormat("en-US", {
  calendar: "gregory"
});

fmt.format(new Date(2026, 0, 1));

Григорианская система:

  • 12 месяцев
  • фиксированная структура года
  • широко принята в международных стандартах
  • используется по умолчанию почти во всех западных локалях

Если календарь не указан, Intl выбирает его автоматически на основе локали.


Доступные календарные системы

Список поддерживаемых календарей можно получить через:

Intl.supportedValuesOf("calendar");

Типичный набор (зависит от реализации ICU):

  • gregory
  • buddhist
  • chinese
  • coptic
  • ethiopic
  • hebrew
  • indian
  • islamic
  • islamic-umalqura
  • islamic-civil
  • islamic-tbla
  • japanese
  • persian
  • roc

Каждая система определяет:

  • начало года
  • структуру месяцев
  • правила високосных лет
  • историческую эпоху

Календарь как часть локали

Календарь можно задавать через Unicode extension в строке локали:

const fmt = new Intl.DateTimeFormat("ar-SA-u-ca-islamic");

или:

const fmt = new Intl.DateTimeFormat("ja-JP-u-ca-japanese");

Такой подход важнее, чем опция calendar, потому что он влияет не только на календарь, но и на сопутствующие культурные настройки.


Islamic календарные системы

Исламские календари основаны на лунных циклах, что приводит к смещению дат относительно солнечного года.

Основные варианты:

  • islamic — табличный вариант
  • islamic-umalqura — официальный календарь Саудовской Аравии
  • islamic-civil — гражданская версия
  • islamic-tbla — табличный алгоритм

Пример:

const fmt = new Intl.DateTimeFormat("ar-SA-u-ca-islamic-umalqura", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

Особенности:

  • год короче солнечного примерно на 10–11 дней
  • месяцы сдвигаются относительно сезонов
  • важны религиозные события (Рамадан, Хадж)

Japanese календарь

Японский календарь (japanese) основан на эпохах императоров (nengō).

Пример:

const fmt = new Intl.DateTimeFormat("ja-JP-u-ca-japanese");
fmt.format(new Date(2026, 0, 1));

Структура:

  • годы считаются от начала эпохи
  • смена императора = новая эпоха
  • возможны даты вида: Reiwa 8

Особенность:

  • один и тот же григорианский год может соответствовать разным эпохам

Buddhist календарь

Используется в Таиланде и некоторых странах Юго-Восточной Азии.

const fmt = new Intl.DateTimeFormat("th-TH-u-ca-buddhist");

Особенности:

  • эпоха начинается на 543 года раньше григорианской
  • 2026 год → 2569 год

Hebrew календарь

Лунно-солнечная система:

const fmt = new Intl.DateTimeFormat("he-IL-u-ca-hebrew");

Особенности:

  • сложные правила вставки дополнительных месяцев
  • религиозная основа
  • используется для еврейских праздников

Chinese календарь

const fmt = new Intl.DateTimeFormat("zh-CN-u-ca-chinese");

Особенности:

  • циклическая система (60-летний цикл)
  • сочетание небесных стволов и земных ветвей
  • используется для традиционных праздников

Persian календарь

const fmt = new Intl.DateTimeFormat("fa-IR-u-ca-persian");

Особенности:

  • солнечный календарь
  • высокая точность относительно сезонов
  • официальный календарь Ирана и Афганистана (вариации)

Результирующие параметры через resolvedOptions

Любой форматтер можно проанализировать:

const fmt = new Intl.DateTimeFormat("en-US-u-ca-islamic");

fmt.resolvedOptions();

Результат включает:

  • calendar
  • locale
  • timeZone
  • numberingSystem

Это ключевой способ определить, какой календарь фактически используется.


Влияние календаря на форматирование

Календарь влияет на:

  • значение года
  • отображение месяцев
  • наличие дополнительных полей (эпоха)
  • формат относительных дат

Пример:

const fmt = new Intl.DateTimeFormat("ja-JP-u-ca-japanese", {
  era: "long",
  year: "numeric",
  month: "long",
  day: "numeric"
});

В результате может появиться:

  • “Reiwa 8”
  • вместо “2026”

Календарь и локаль: приоритеты

Система выбора календаря работает по приоритетам:

  1. Явно указанный calendar в options
  2. Unicode extension -u-ca-
  3. Значение по умолчанию локали
  4. Глобальный дефолт ICU (обычно gregory)

Пример:

new Intl.DateTimeFormat("en-US", {
  calendar: "buddhist"
});

перекрывает:

new Intl.DateTimeFormat("en-US-u-ca-gregory");

Совместимость и ограничения

Не все календарные системы равнозначны:

  • часть календарей ограничена ICU реализацией
  • поведение может отличаться между Node.js и браузерами
  • некоторые календари доступны только для форматирования, но не для вычислений

Важно:

  • Date не поддерживает альтернативные календари внутри себя
  • календарь применяется только на этапе форматирования

Календарные системы и Temporal (контекст)

Хотя Temporal API ещё не является полностью унифицированным во всех окружениях, его модель напрямую учитывает календарные системы:

  • PlainDate
  • Calendar как отдельная сущность

Это усиливает роль календарей как независимого слоя поверх временной шкалы.


Форматирование частей даты

formatToParts показывает влияние календаря на структуру:

const fmt = new Intl.DateTimeFormat("ar-SA-u-ca-islamic", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

fmt.formatToParts(new Date());

Части могут включать:

  • year
  • month
  • day
  • literal

Но значения года и месяца уже преобразованы в соответствии с календарём.


Практическое поведение календарей

Календарные системы в Intl работают как слой трансформации:

timestamp → Gregorian breakdown → calendar conversion → localized formatting

Из этого следуют ключевые свойства:

  • один timestamp может иметь разные календарные представления
  • календарь не влияет на точность времени
  • календарь влияет только на человеческое восприятие даты

Unicode extension и комбинирование параметров

Календарь может комбинироваться с другими параметрами:

ja-JP-u-ca-japanese-nu-arab

где:

  • ca — календарь
  • nu — система чисел

Пример:

new Intl.DateTimeFormat("ja-JP-u-ca-japanese-nu-jpan");

Это позволяет одновременно менять:

  • календарную систему
  • способ записи чисел
  • локализационные правила

Поведение при отсутствии поддержки

Если указанный календарь не поддерживается:

  • происходит fallback к ближайшему доступному
  • обычно возвращается gregory
  • ошибок выполнения не возникает

Это гарантирует стабильность API.


Роль календаря в интернационализации

Календарные системы обеспечивают:

  • культурную точность отображения дат
  • поддержку религиозных и исторических традиций
  • совместимость с региональными стандартами
  • единый интерфейс поверх разных систем летоисчисления

Intl API скрывает сложность преобразований, предоставляя унифицированную модель форматирования поверх множества календарных логик.