Нумерационная система

Нумерационная система определяет, какие символы используются для отображения чисел в форматируемых строках даты и времени. В контексте JavaScript и международной локализации эта концепция тесно связана со стандартом Unicode CLDR и API Intl, на котором основана библиотека Luxon. Вместо привычных арабских цифр 0–9 могут применяться индийские, арабские-индийские, персидские и другие наборы символов, что влияет на визуальное представление всех числовых компонентов даты.

В Luxon нумерационная система не является отдельной сущностью внутри класса DateTime, но задаётся через параметры форматирования, которые проксируются в Intl.DateTimeFormat. Ключевым механизмом становится опция numberingSystem, которая может быть передана через конфигурацию локали или форматтера.


Основы поддержки нумерационных систем в Intl

В основе Luxon лежит использование Intl.DateTimeFormat, который поддерживает параметр:

  • numberingSystem

Он влияет на отображение всех чисел в результирующей строке: день месяца, год, часы, минуты и секунды.

Пример доступных систем:

  • latn — латинские цифры (0–9)
  • arab — арабско-индийские цифры
  • arabext — расширенные арабские цифры
  • deva — деванагари
  • thai — тайские цифры

Эта система применяется на уровне локали и может быть частью строки локали вида:

ar-EG-u-nu-arab

где nu указывает на нумерационную систему.


Luxon и проксирование Intl-настроек

Luxon не реализует собственную систему числовых символов. Вместо этого он передаёт настройки в Intl, сохраняя поведение стандартным и предсказуемым.

Ключевой момент: все параметры форматирования даты и времени, включая нумерационную систему, передаются через toLocaleString, toFormat (частично) и Intl форматтеры внутри библиотеки.

В Luxon это проявляется через объект DateTime:

  • DateTime.toLocaleString
  • DateTime.toFormat
  • DateTime.toLocaleString(DateTime.DATETIME_MED) и другие presets

Управление нумерационной системой через локаль

Основной способ задания нумерационной системы — использование расширенных локалей Unicode.

Пример: арабские цифры

const dt = DateTime.now().setLocale('ar-EG-u-nu-arab');

dt.toLocaleString(DateTime.DATETIME_FULL);

Результат будет содержать цифры вида:

٢٣ / ٠٥ / ٢٠٢٦

вместо:

23 / 05 / 2026

Пример: тайская нумерация

const dt = DateTime.now().setLocale('th-TH-u-nu-thai');
dt.toLocaleString(DateTime.DATE_FULL);

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

๒๓ พฤษภาคม ๒๕๖๙

Поведение Luxon при отсутствии явного numberingSystem

Если нумерационная система не указана:

  • используется системная локаль среды выполнения
  • применяется дефолтная система latn
  • поведение зависит от Node.js или браузера

Luxon не выполняет трансформацию цифр самостоятельно, что гарантирует соответствие спецификации ECMAScript Internationalization API.


Связь с форматированием через DateTimeFormat

При использовании Luxon фактически создаётся Intl.DateTimeFormat примерно следующего вида:

new Intl.DateTimeFormat(locale, {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  numberingSystem: 'arab'
});

Luxon автоматически генерирует подобные конфигурации внутри своих preset-форматов.


Ограничения нумерационных систем в Luxon

Несмотря на поддержку через Intl, существуют ограничения:

  • нельзя напрямую задать numberingSystem через стандартный API Luxon без использования локали
  • поведение зависит от реализации Intl в окружении
  • не все комбинации локалей и систем поддерживаются одинаково в старых окружениях Node.js

Также важно учитывать, что toFormat (строковый форматтер Luxon) не преобразует цифры через numberingSystem — он опирается на Intl только в тех частях, где это возможно.


Использование в сложных локализациях

В многоязычных приложениях нумерационная система часто меняется вместе с локалью:

  • арабский язык → арабско-индийские цифры
  • персидский → персидские цифры
  • хинди → деванагари
  • английский → латинские цифры

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


Влияние на производительность и кэширование

Каждое изменение локали с различной нумерационной системой может приводить к созданию нового экземпляра Intl.DateTimeFormat. Внутри Luxon применяется кэширование форматтеров, что снижает накладные расходы при повторных вызовах с одинаковыми параметрами.

Ключ кэширования включает:

  • локаль
  • календарь
  • нумерационную систему
  • набор опций форматирования

Это позволяет избежать повторной инициализации тяжелых объектов Intl.


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

Нумерационная система часто используется совместно с календарями, отличными от григорианского:

  • исламский календарь
  • индийский национальный календарь
  • японская эра

Luxon через Intl поддерживает комбинации, где календарь и нумерация задаются одновременно:

ar-SA-u-ca-islamic-nu-arab

Здесь одновременно определяются:

  • календарь: исламский
  • нумерация: арабско-индийская

Практическая модель преобразования

При форматировании Luxon проходит цепочку:

  1. DateTime хранит внутреннее представление времени в миллисекундах
  2. применяется локаль с расширениями Unicode
  3. создаётся Intl.DateTimeFormat
  4. форматтер генерирует строку с учётом numberingSystem
  5. результат возвращается пользователю

Цифры не преобразуются вручную — они генерируются на уровне ICU-библиотеки, встроенной в среду выполнения.


Типичные сценарии применения

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

Поведение при сериализации

При преобразовании DateTime в JSON через toISO, toJSON или toString нумерационная система не применяется, поскольку эти форматы являются стандартизированными и не зависят от локали. Это разделяет две модели представления:

  • локализованное отображение (Intl + numberingSystem)
  • машинно-ориентированное представление (ISO 8601)