Локализованный парсинг

Moment.js поддерживает разбор строк дат с учётом локали, что позволяет интерпретировать даты не только в формате ISO или фиксированных числовых шаблонов, но и в человеко-читаемых выражениях на разных языках. Локализованный парсинг особенно важен при работе с интерфейсами, где пользователь вводит дату в привычной для него форме: «12 марта 2024», «5 janvier 2023», «23 Oktober 2022».

Механизм локализации влияет на то, как библиотека распознаёт названия месяцев, дней недели, порядковые числительные и форматные токены.


Базовый принцип локализованного парсинга

При разборе строки Moment.js использует текущую локаль, которая определяет:

  • названия месяцев;
  • сокращения месяцев;
  • названия дней недели;
  • правила чтения порядковых чисел;
  • форматы даты по умолчанию.

Если локаль не задана явно, используется en (английская).

moment.locale('fr');

const date = moment('12 mars 2024', 'DD MMMM YYYY');

В данном случае слово mars будет интерпретировано как март благодаря французской локали.


Форматы с локализованными токенами

Локализованный парсинг тесно связан с форматными токенами:

  • MMMM — полное название месяца
  • MMM — сокращённое название месяца
  • dddd — день недели полностью
  • ddd — сокращённый день недели
  • Do — день месяца с порядковым суффиксом (1st, 2nd, 3rd…)

Пример:

moment.locale('de');

const m = moment('23 Oktober 2023', 'D MMMM YYYY');

Здесь Oktober корректно интерпретируется как октябрь в немецкой локали.


Разбор дат с различными локалями

Каждая локаль содержит собственный словарь месяцев и дней недели. При смене локали меняется интерпретация входной строки.

moment.locale('es');

const a = moment('15 agosto 2022', 'D MMMM YYYY');

moment.locale('it');

const b = moment('15 agosto 2022', 'D MMMM YYYY');

В обоих случаях строка корректно распознаётся, так как слово agosto присутствует в обеих локалях.


Явное указание локали при парсинге

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

const d1 = moment('12 marzo 2024', 'DD MMMM YYYY', 'es');
const d2 = moment('12 marzo 2024', 'DD MMMM YYYY', 'it');

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


Строгий локализованный парсинг

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

moment.locale('ru');

const d = moment('5 январь 2023', 'D MMMM YYYY', true);

Если строка не соответствует словарю локали или формату, результат будет невалидным:

moment('5 january 2023', 'D MMMM YYYY', true).isValid(); // false

Поддержка порядковых чисел в локалях

В некоторых языках порядок чисел имеет собственные правила: 1st, 2nd, 3rd, 4th в английском языке или локализованные формы в других языках.

moment.locale('en');

const x = moment('21st March 2024', 'Do MMMM YYYY', true);

В других локалях использование Do может интерпретироваться иначе или вовсе не поддерживаться, что влияет на валидность разбора.


Особенности разбора сокращённых месяцев

Сокращения месяцев зависят от локали и могут конфликтовать между языками. Например, mar может означать март в английском и испанском контексте.

moment.locale('en');

moment('Mar 10 2024', 'MMM D YYYY');

При смене локали интерпретация может измениться:

moment.locale('fr');

moment('mars 10 2024', 'MMMM D YYYY');

Пользовательские локали и их влияние на парсинг

Локали могут быть определены вручную, что позволяет расширять или изменять стандартное поведение парсинга.

moment.defineLocale('custom', {
  months: 'Янв_Фев_Мар_Апр_Май_Июн_Июл_Авг_Сен_Окт_Ноя_Дек'.split('_'),
  monthsParseExact: true,
  weekdays: 'Вск_Пнд_Втр_Срд_Чтв_Птн_Сбт'.split('_'),
  longDateFormat: {
    L: 'DD.MM.YYYY'
  }
});

После этого локаль начинает влиять на интерпретацию строк:

moment.locale('custom');

moment('12 Мар 2024', 'D MMM YYYY');

Обновление локали и влияние на уже созданные парсеры

Изменение локали влияет только на последующие операции, но не пересчитывает уже созданные объекты.

moment.locale('en');
const m1 = moment('March 5 2024', 'MMMM D YYYY');

moment.locale('fr');
const m2 = moment('mars 5 2024', 'MMMM D YYYY');

Каждый объект использует локаль в момент своего создания.


Неоднозначные строки и fallback-поведение

Если строка содержит неоднозначные элементы, Moment.js пытается интерпретировать их согласно текущей локали и формату. При невозможности сопоставления результат становится невалидным, но библиотека не выбрасывает исключение.

moment('foo bar', 'D MMMM YYYY').isValid(); // false

Влияние локали на двухзначные годы

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

moment.parseTwoDigitYear = function (input) {
  return Number(input) + 2000;
};

moment('12 05 24', 'DD MM YY');

Хотя это не строго локализованная функция, она часто используется совместно с локальными форматами дат.


Комбинация локалей и кастомных форматов

Локализованный парсинг становится особенно мощным при использовании пользовательских форматов:

moment.locale('ru');

const format = 'D MMMM YYYY [г.]';
const result = moment('5 марта 2024 г.', format);

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


Ограничения локализованного парсинга

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

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