Буддийский календарь

API интернационализации ECMAScript (Intl) предоставляет единый механизм форматирования дат и времени с учётом культурных и региональных различий. Одним из ключевых аспектов является поддержка альтернативных календарей, среди которых буддийский календарь используется в ряде стран Юго-Восточной Азии и представляет собой надстройку над григорианской системой с иной системой летоисчисления.

Буддийский календарь в JavaScript не является отдельной моделью времени: он реализуется как режим отображения поверх стандартного Date, где меняется только представление года и эпохи, но не внутренняя временная модель.


Модель времени в Intl и роль календарей

Внутренне JavaScript использует Unix-время (timestamp) — количество миллисекунд с 1 января 1970 года UTC. Объект Date не хранит календарную систему, а лишь абсолютный момент времени.

Intl.DateTimeFormat накладывает на этот момент времени правила форматирования:

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

Календарь является частью Unicode Locale Identifier и может быть задан через:

  • опцию calendar
  • или расширение u-ca в строке локали

Буддийский календарь и система летоисчисления

Буддийский календарь, используемый в JavaScript через Intl, соответствует Thai Buddhist Era (BE).

Его ключевая особенность:

  • год смещён относительно григорианского на +543 года

  • например:

    • 2026 (AD) → 2569 (BE)

Это не альтернативная система времени, а альтернативное представление года.


Способы включения буддийского календаря

Через параметр calendar

const formatter = new Intl.DateTimeFormat('th-TH', {
  calendar: 'buddhist',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

console.log(formatter.format(new Date()));

В этом случае локаль может быть любой, но чаще используется th-TH, поскольку тайский язык исторически связан с буддийским летоисчислением.


Через Unicode extension u-ca-buddhist

const formatter = new Intl.DateTimeFormat('th-TH-u-ca-buddhist');

console.log(formatter.format(new Date()));

Здесь календарь задаётся как часть BCP 47-тега локали:

  • th-TH — базовая локаль
  • u-ca-buddhist — Unicode extension (calendar = buddhist)

Этот способ считается предпочтительным, когда требуется компактная и декларативная настройка локали.


Форматирование даты в буддийской системе

const date = new Date('2026-01-01');

const fmtGregorian = new Intl.DateTimeFormat('th-TH', {
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

const fmtBuddhist = new Intl.DateTimeFormat('th-TH', {
  calendar: 'buddhist',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

fmtGregorian.format(date);
fmtBuddhist.format(date);

Результат иллюстрирует ключевую особенность: различие только в годе и обозначении эпохи, при неизменной дате.


Структура параметров форматирования

Intl.DateTimeFormat использует набор опций, которые остаются неизменными независимо от календаря:

  • year: "numeric" | "2-digit"
  • month: "numeric" | "2-digit" | "long" | "short" | "narrow"
  • day: "numeric" | "2-digit"
  • hour, minute, second
  • timeZone
  • weekday

Календарь влияет только на интерпретацию года и иногда на локальные правила отображения дат.


Влияние локали на буддийский календарь

Локаль определяет языковое оформление результата:

new Intl.DateTimeFormat('th-TH-u-ca-buddhist', {
  year: 'numeric',
  month: 'long',
  day: 'numeric'
}).format(new Date());

Для th-TH результат будет на тайском языке с буддийским летоисчислением.

Если заменить локаль:

new Intl.DateTimeFormat('en-US-u-ca-buddhist', {
  year: 'numeric',
  month: 'long',
  day: 'numeric'
}).format(new Date());

то формат останется буддийским, но язык будет английским, а стиль отображения адаптируется под региональные правила США.


Разница между календарём и эпохой

В буддийской системе используется собственная эпоха:

  • Gregorian Era: AD (Anno Domini)
  • Buddhist Era: BE (Buddhist Era)

Intl автоматически подставляет корректную эпоху при выборе календаря.

const fmt = new Intl.DateTimeFormat('th-TH-u-ca-buddhist', {
  year: 'numeric'
});

fmt.format(new Date('2026-01-01'));

Вывод будет содержать год 2569 BE.


Поддерживаемые значения календарей

Intl опирается на Unicode Calendar Identifier. Среди доступных календарей:

  • gregory
  • buddhist
  • japanese
  • islamic
  • hebrew
  • chinese
  • persian
  • indian

Для проверки поддержки в среде используется:

Intl.supportedValuesOf('calendar');

Если buddhist присутствует, форматирование с этим календарём гарантированно поддерживается.


Поведение при форматировании диапазонов и частей даты

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

  • год преобразуется в систему летоисчисления
  • месяц и день остаются календарно эквивалентными
  • день недели не зависит от календаря
const fmt = new Intl.DateTimeFormat('th-TH-u-ca-buddhist', {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

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

  • локализованное название дня недели
  • буддийский год
  • локализованные названия месяца

Ограничения Intl при работе с буддийским календарём

Несмотря на поддержку календарей, существуют фундаментальные ограничения:

  • Intl не изменяет внутренний тип Date
  • невозможно получить “объект буддийской даты”
  • отсутствует обратное преобразование строки в дату с учётом календаря
  • парсинг дат не входит в область Intl

Таким образом:

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

Поведение при изменении года и переходных значениях

Поскольку буддийский календарь — это смещение:

  • 1 января 1970 (Unix epoch) = 2513 BE
  • каждый последующий год увеличивается синхронно с Gregorian +543
new Intl.DateTimeFormat('th-TH-u-ca-buddhist', {
  year: 'numeric'
}).format(new Date(0));

Это подчёркивает, что система не имеет собственного “начала времени”, а лишь отображает другую шкалу лет.


Совместное использование с другими форматами

Календарь можно комбинировать с любыми форматами:

new Intl.DateTimeFormat('th-TH-u-ca-buddhist', {
  dateStyle: 'full',
  timeStyle: 'long',
  timeZone: 'Asia/Bangkok'
});

Комбинация:

  • dateStyle/timeStyle задаёт уровень детализации
  • calendar задаёт систему летоисчисления
  • timeZone фиксирует локальное время

Unicode extension и приоритет параметров

Если календарь задан двумя способами:

new Intl.DateTimeFormat('th-TH-u-ca-buddhist', {
  calendar: 'gregory'
});

приоритет имеет явный параметр calendar, а не расширение локали.

Это важно при динамической генерации настроек форматирования.


Поведение в разных окружениях выполнения

Реализация зависит от движка:

  • V8 (Chrome, Node.js)
  • SpiderMonkey (Firefox)
  • JavaScriptCore (Safari)

Хотя спецификация едина, список поддерживаемых календарей может отличаться. Однако буддийский календарь входит в базовый набор Unicode CLDR и поддерживается практически повсеместно.


Типичные сценарии использования

Буддийский календарь в Intl используется там, где требуется:

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

Влияние на сортировку и сравнение дат

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

  • сравнение дат (Date-объекты сравниваются по timestamp)
  • сортировку временных значений
  • вычисления интервалов

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

new Date('2026-01-01') > new Date('2025-01-01'); // true

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


Итоговая модель поведения календаря в Intl

  • вход: абсолютный момент времени (Date)
  • обработка: применение локали + календаря
  • выход: локализованная строка
  • внутренняя модель времени не изменяется
  • буддийский календарь реализуется как смещение года +543 и локализация вывода