Moment.js предоставляет механизм обработки входных строк даты, которые могут соответствовать различным шаблонам. Это особенно важно в случаях, когда источник данных неоднороден: пользовательский ввод, внешние API, импортированные файлы или исторические данные, где форматирование не унифицировано.
Основная идея заключается в передаче массива форматов в функцию парсинга. Библиотека последовательно проверяет строку даты по каждому шаблону до первого успешного совпадения.
При вызове moment() можно передать не один формат, а
несколько:
moment("2026-05-21", ["YYYY-MM-DD", "DD/MM/YYYY", "MM-DD-YYYY"]);
В данном случае происходит последовательная попытка распознать строку:
YYYY-MM-DDDD/MM/YYYYMM-DD-YYYYПервый подходящий формат завершает процесс парсинга.
Такой механизм позволяет создавать устойчивые к вариативности входных данных системы без необходимости предварительной нормализации строк.
Порядок элементов в массиве имеет прямое значение. Moment.js не анализирует «наиболее вероятный» формат, а действует строго последовательно.
moment("01-02-2026", ["DD-MM-YYYY", "MM-DD-YYYY"]);
Здесь результат будет интерпретирован как 1 февраля 2026 года,
поскольку первым проверяется формат DD-MM-YYYY.
Если поменять порядок:
moment("01-02-2026", ["MM-DD-YYYY", "DD-MM-YYYY"]);
результат изменится и будет трактоваться как 2 января 2026 года.
Подобное поведение требует строгого контроля порядка форматов при проектировании системы обработки дат.
Moment.js поддерживает «строгий» режим, при котором формат должен совпадать полностью, без частичных соответствий.
moment("2026-5-1", ["YYYY-MM-DD"], true);
В строгом режиме строка "2026-5-1" не будет считана
корректной для формата YYYY-MM-DD, так как ожидается
строгое соответствие двухзначных компонентов месяца и дня.
При использовании массива форматов строгий режим применяется ко всем элементам списка:
moment("21/05/2026", ["YYYY-MM-DD", "DD/MM/YYYY"], true);
Если ни один формат не соответствует строго, результатом становится невалидная дата.
Moment.js поддерживает ISO 8601 как отдельный стандартный случай. При передаче массива форматов ISO может использоваться как один из вариантов или как отдельная ветка обработки.
moment("2026-05-21T14:30:00Z", ["YYYY-MM-DD", moment.ISO_8601]);
ISO-формат обладает более высокой приоритетностью в смысле точности распознавания сложных временных меток, включающих временную зону.
Использование moment.ISO_8601 позволяет интегрировать
строгие стандарты обмена данными вместе с локальными форматами.
В многоязычных приложениях входные данные часто зависят от локали пользователя. Например, европейские и американские форматы даты различаются порядком дня и месяца.
moment("21.05.2026", ["DD.MM.YYYY", "MM-DD-YYYY", "YYYY/MM/DD"]);
Подобные комбинации позволяют покрывать широкий спектр пользовательских привычек без необходимости предварительного преобразования строки.
Локальные форматы могут включать:
Moment.js допускает частичное соответствие при нестрогом парсинге. Например:
moment("2026-05", ["YYYY-MM-DD"]);
В этом случае день может быть установлен по умолчанию (обычно 1-е число месяца), если формат допускает недостающие компоненты.
При использовании массива форматов это поведение сохраняется для каждого элемента списка отдельно. Как только находится первый подходящий формат, дальнейшие проверки не выполняются.
Одним из сложных случаев является работа с датами, которые могут быть интерпретированы несколькими способами:
moment("03/04/2026", ["MM/DD/YYYY", "DD/MM/YYYY"]);
Такие строки требуют строгого определения приоритетного формата, поскольку обе интерпретации валидны.
При изменении порядка:
moment("03/04/2026", ["DD/MM/YYYY", "MM/DD/YYYY"]);
результат полностью меняется.
Для предотвращения ошибок в таких случаях часто используется явная валидация:
const m = moment("03/04/2026", ["DD/MM/YYYY", "MM/DD/YYYY"], true);
if (!m.isValid()) {
// обработка ошибки
}
Массив форматов может включать не только даты, но и комбинации даты и времени:
moment("2026-05-21 14:30", [
"YYYY-MM-DD HH:mm",
"DD.MM.YYYY HH:mm",
"YYYY/MM/DD HH:mm:ss"
]);
Moment.js сопоставляет как дату, так и временные компоненты, включая:
HH, hh)mm)ss)SSS)Отсутствующие элементы могут быть заполнены значениями по умолчанию.
При использовании большого массива форматов следует учитывать, что каждый неуспешный шаблон требует дополнительной проверки. Это может влиять на производительность при массовом парсинге.
const formats = [
"YYYY-MM-DD",
"DD/MM/YYYY",
"MM-DD-YYYY",
"YYYY/MM/DD",
"DD.MM.YYYY",
"YYYYMMDD"
];
При обработке тысяч строк последовательная проверка каждого формата может стать узким местом.
Оптимизация достигается за счёт:
После парсинга важно учитывать результат функции
isValid():
const date = moment("31/02/2026", ["DD/MM/YYYY", "YYYY-MM-DD"]);
date.isValid(); // false
Некорректные даты (например, 31 февраля) могут пройти через синтаксический этап парсинга, но будут отвергнуты на уровне календарной логики.
При использовании нескольких форматов это поведение не изменяется — проверка валидности выполняется уже после успешного сопоставления строки с одним из шаблонов.
Moment.js использует набор токенов для описания форматов:
YYYY — годMM — месяцDD — деньHH — часы (24-часовой формат)mm — минутыss — секундыКомбинации этих токенов позволяют строить сложные шаблоны:
moment("2026|05|21 14-30", [
"YYYY|MM|DD HH-mm",
"YYYY-MM-DD HH:mm"
]);
При работе с несколькими форматами важно соблюдать консистентность токенов, иначе возможны неоднозначные совпадения.
Moment.js поддерживает форматы, содержащие текстовые вставки:
moment("2026 год 21 мая", [
"YYYY год DD MMMM",
"DD MMMM YYYY"
]);
В таких случаях критически важна локаль, так как названия месяцев зависят от языковых настроек:
moment.locale("ru");
При отсутствии корректной локали сопоставление может не сработать даже при правильной структуре строки.
Множественные форматы используются в типичных задачах обработки данных:
1. Импорт CSV файлов
moment(value, [
"YYYY-MM-DD",
"DD/MM/YYYY",
"MM/DD/YYYY",
"YYYYMMDD"
]);
2. Обработка пользовательского ввода
moment(input, [
"DD.MM.YYYY",
"D.M.YYYY",
"YYYY-MM-DD"
]);
3. Интеграция с API разных сервисов
moment(apiDate, [
moment.ISO_8601,
"YYYY-MM-DDTHH:mm:ss",
"YYYY-MM-DD"
]);
Каждый источник может использовать собственные правила сериализации дат, что делает массив форматов универсальным адаптером.
Если ни один формат не совпал, Moment.js возвращает невалидный объект:
const m = moment("invalid-date", ["YYYY-MM-DD", "DD/MM/YYYY"]);
m.isValid(); // false
Такой объект всё ещё существует, но все операции над ним будут возвращать некорректные или пустые значения.
При обработке массивов форматов это поведение важно учитывать, поскольку ошибка может быть скрыта на этапе парсинга и проявиться только при использовании результата.
При отсутствии входных данных или при частично распознанных форматах возможна подстановка текущей даты:
moment("", ["YYYY-MM-DD"]);
В таких случаях результат зависит от конфигурации и контекста вызова, но чаще всего используется текущее время как fallback.
После успешного парсинга с несколькими форматами объект Moment.js может быть использован в цепочках:
moment("21-05-2026", ["DD-MM-YYYY", "YYYY/MM/DD"])
.add(5, "days")
.format("YYYY-MM-DD");
Множественные форматы влияют только на этап инициализации, не затрагивая дальнейшие операции.
Локаль влияет не только на текстовые месяцы, но и на допустимые варианты парсинга:
moment.locale("fr");
moment("21 mai 2026", [
"DD MMMM YYYY",
"YYYY-MM-DD"
]);
При смене локали один и тот же массив форматов может давать разные результаты распознавания из-за различий в названиях месяцев и дней недели.