Календарь и система счисления

В JavaScript календарная система задаётся через параметр calendar, который входит в состав локали или передаётся через объект options в форматерах Intl.DateTimeFormat, Intl.RelativeTimeFormat, а также в ряде других API, связанных с датами.

Календарь определяет правила разбиения времени на годы, месяцы и дни, а также способ вычисления этих значений. Стандартная система в большинстве окружений — григорианская (gregory), однако ICU-реализация Intl поддерживает множество альтернативных календарей.

Основные календарные системы

Наиболее распространённые значения параметра calendar:

  • gregory — григорианский календарь (де-факто стандарт)
  • iso8601 — календарь ISO, основанный на неделях
  • buddhist — буддийский календарь (используется в Таиланде)
  • chinese — традиционный китайский календарь
  • coptic — коптский календарь
  • ethiopic — эфиопские календарные системы
  • hebrew — еврейский календарь
  • indian — индийский национальный календарь
  • islamic / islamic-umalqura / islamic-civil — исламские календари с различными алгоритмами расчёта
  • persian — персидский календарь

Каждая система влияет на вычисление года, месяца и даже структуру месяцев.

Использование календаря в Intl.DateTimeFormat

Календарь задаётся через локаль с Unicode extension или через опции форматирования.

Через локаль

const date = new Date();

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

fmt.format(date);

В данном примере:

  • u-ca-islamic включает исламский календарь
  • локаль en определяет язык вывода

Через options (ограниченная поддержка)

const fmt = new Intl.DateTimeFormat("ar", {
  calendar: "islamic-umalqura",
  year: "numeric",
  month: "2-digit",
  day: "2-digit"
});

fmt.format(new Date());

Параметр calendar напрямую работает не во всех окружениях одинаково, но при поддержке ICU он переопределяет календарную систему.

Unicode Extension и ключ ca

Формат Unicode extension позволяет комбинировать параметры локали:

language[-script][-region]-u-ca-calendar

Примеры:

  • en-u-ca-gregory
  • ar-u-ca-islamic
  • fa-u-ca-persian
new Intl.DateTimeFormat("fa-u-ca-persian").format(new Date());

Различия календарных систем

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

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

Например:

Система Особенности
gregory 12 месяцев, фиксированная структура
islamic лунный календарь, год короче
chinese циклическая система с високосными месяцами
hebrew лунно-солнечная система

Класс Intl.DateTimeFormat и календарные режимы

Intl.DateTimeFormat — основной инструмент работы с календарями.

Форматирование с учётом календаря

const fmtGregorian = new Intl.DateTimeFormat("en-u-ca-gregory", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

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

const date = new Date();

fmtGregorian.format(date);
fmtHijri.format(date);

Обе строки представляют одну и ту же дату, но в разных календарных системах.

Использование formatToParts

Метод formatToParts позволяет разобрать календарное представление на компоненты:

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

fmt.formatToParts(new Date());

Результат:

[
  { type: "month", value: "Rabi' I" },
  { type: "day", value: "12" },
  { type: "year", value: "1446" }
]

Календарь напрямую влияет на структуру этих частей.

API Intl.Calendar

Intl.Calendar предоставляет низкоуровневый доступ к календарным вычислениям. Поддержка зависит от окружения, но в современных реализациях на базе ICU он доступен.

Создание календаря

const cal = new Intl.Calendar("islamic");

Поддерживаемые идентификаторы соответствуют Unicode CLDR.

Основные методы

dateFromFields

Создание даты из календарных полей:

const cal = new Intl.Calendar("gregory");

cal.dateFromFields({
  year: 2025,
  month: 5,
  day: 26
});

year, month, day извлечение

const cal = new Intl.Calendar("islamic");

const date = new Date();

cal.fields(date);

Результат содержит календарно-зависимые значения.

Особенности календарных вычислений

Разные календари по-разному интерпретируют:

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

Например, в исламском календаре год примерно на 10–11 дней короче солнечного года, что приводит к смещению дат относительно григорианской системы.

Система счисления (Numbering System)

Помимо календарей, Intl API поддерживает настройку системы счисления через параметр numberingSystem.

Основные системы счисления

  • latn — латинские цифры (0–9)
  • arab — арабские цифры
  • arabext — расширенные арабские цифры
  • deva — деванагари
  • beng — бенгальская система
  • thai — тайская система
  • hebr — еврейская система
  • fullwide — полноширинные символы

Использование через Intl.NumberFormat

const nf = new Intl.NumberFormat("ar-u-nu-arab", {
  numberingSystem: "arab"
});

nf.format(123456);

Unicode extension ключ nu

Аналогично календарям, система счисления задаётся через nu:

  • en-u-nu-latn
  • ar-u-nu-arab
  • hi-u-nu-deva
new Intl.NumberFormat("hi-u-nu-deva").format(12345);

Результат будет отображён в деванагари-цифрах.

Взаимодействие календаря и системы счисления

Календарь и система счисления работают независимо, но часто используются вместе в локалях.

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

fmt.format(new Date());

В данном случае:

  • календарь исламский
  • цифры арабские
  • язык арабский

Поведение ICU и зависимости от окружения

Поддержка календарей и систем счисления зависит от ICU-библиотеки, встроенной в среду выполнения JavaScript.

Различия могут включать:

  • отсутствие редких календарей в минимальных сборках Node.js
  • ограничение ICU data в браузерах
  • различия между системами (Windows, Linux, mobile engines)

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

Intl.supportedValuesOf("calendar");
Intl.supportedValuesOf("numberingSystem");

Локализационные комбинации

Unicode extension позволяет комбинировать параметры:

language-u-ca-calendar-nu-numberingSystem

Примеры:

  • en-u-ca-buddhist-nu-thai
  • th-u-ca-buddhist-nu-thai
  • ar-u-ca-islamic-nu-arabext
new Intl.DateTimeFormat("th-u-ca-buddhist-nu-thai").format(new Date());

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

Особенности отображения месяцев и эпох

В разных календарях:

  • названия месяцев локализуются
  • количество месяцев может отличаться
  • эпохи могут быть иными (например, в буддийском календаре отсчёт ведётся от смерти Будды)
new Intl.DateTimeFormat("th-u-ca-buddhist", {
  year: "numeric",
  month: "long"
}).format(new Date());

Год будет смещён относительно григорианского на 543 года.

Календарные вычисления и нормализация дат

При работе с Intl.Calendar и форматерами происходит нормализация:

  • входная дата всегда интерпретируется как момент времени (timestamp)
  • календарь лишь отображает её в другой системе координат
  • обратное преобразование зависит от правил календаря
const cal = new Intl.Calendar("persian");

const fields = cal.fields(new Date());

Результат отражает персидскую систему летоисчисления.

Ограничения и особенности реализации

  • не все календари поддерживаются одинаково во всех средах
  • поведение Intl.Calendar может отличаться между движками
  • некоторые комбинации ca и nu игнорируются fallback-локалью
  • ISO-календарь не всегда доступен как полноценная система отображения

При этом Intl.DateTimeFormat остаётся основным стабильным инструментом работы с календарями и числовыми системами в JavaScript.