Moment.js при разборе строковых значений дат не использует механизм
исключений как основной способ сигнализации об ошибке. В большинстве
случаев библиотека не выбрасывает throw, а возвращает
объект момента, помеченный как невалидный. Это ключевая особенность,
определяющая стратегию обработки ошибок.
После любого парсинга необходимо проверять результат через:
moment.isValid()const m = moment("невалидная дата");
if (!m.isValid()) {
// обработка ошибки
}
Важно: отсутствие исключения не означает корректный результат парсинга.
При некорректном вводе Moment.js создаёт объект, который:
Invalid date при форматированииconst m = moment("32-13-2020");
console.log(m.format()); // Invalid date
console.log(m.isValid()); // false
При использовании строгого режима форматирования несоответствие приводит к невалидному результату:
const m = moment("2020/31/12", "YYYY-MM-DD", true);
console.log(m.isValid()); // false
Строгий режим (true третьим параметром) запрещает любые
отклонения.
Даже при формально корректной структуре строка может содержать недопустимые значения:
moment("2020-02-30").isValid(); // false
moment("2020-13-01").isValid(); // false
moment("2020-00-10").isValid(); // false
Moment.js выполняет нормализацию календарных значений и отклоняет выход за диапазон.
При слабом (non-strict) парсинге возможны неожиданные интерпретации:
moment("2020-10-05", "MM-DD-YYYY").format(); // интерпретация может отличаться
При неоднозначности порядок интерпретации зависит от формата и локали.
Строгий режим является основным инструментом контроля корректности входных данных.
moment("05/10/2020", "DD-MM-YYYY", true);
Поведение:
Moment.js предоставляет внутренние флаги разбора:
const m = moment("2020-02-30");
console.log(m.parsingFlags());
Типичные флаги:
overflow — выход за пределы диапазона (например, 30
февраля)invalidMonthemptynullInputunusedTokensЭти флаги позволяют определить, почему именно парсинг завершился неудачей.
Некорректные или пустые входные данные часто приводят к невалидному объекту:
moment(null).isValid(); // false
moment(undefined).isValid(); // false
moment("").isValid(); // false
При проектировании слоёв обработки дат такие значения должны фильтроваться до вызова Moment.js.
ISO 8601 формат обрабатывается более предсказуемо, но не гарантирует валидность:
moment("2020-02-30T10:00:00Z").isValid(); // false
moment("2020-02-20T10:00:00Z").isValid(); // true
Несмотря на стандарт, календарная корректность всё равно проверяется.
При использовании локализованных форматов увеличивается вероятность ошибок:
moment("31.12.2020", "L", true);
Проблемные случаи:
const m = moment(input, format, true);
if (!m.isValid()) {
return null;
}
let m = moment(input, "YYYY-MM-DD", true);
if (!m.isValid()) {
m = moment(input, "MM-DD-YYYY", true);
}
function safeParseDate(value) {
const m = moment(value, moment.ISO_8601, true);
if (!m.isValid()) {
return {
error: "invalid_date",
value
};
}
return { date: m };
}
Moment.js не использует try/catch как основной механизм
обработки ошибок при разборе строк. Это приводит к следующим
последствиям:
Invalid dateОшибки парсинга сохраняются при дальнейших операциях:
const m = moment("invalid");
const result = m.add(2, "days").format(); // Invalid date
Любые операции над невалидным объектом сохраняют невалидное состояние.
Некоторые операции могут скрывать первичную проблему, но не исправляют её:
const m = moment("2020-02-30").add(1, "day");
m.isValid(); // false
Moment.js не пытается «починить» некорректные даты автоматически.
format() без проверки
isValid()Invalid date в базе данныхInvalid date как сигнального значенияСтрока Invalid date является лишь представлением
состояния объекта, а не самостоятельной ошибкой. Внутренняя логика
библиотеки опирается на флаги валидности, а не на строковое
представление.
При преобразовании в JSON:
JSON.stringify(moment("invalid"))
Результат зависит от реализации:
{} или строкаПоэтому необходимо извлекать строковое или числовое значение только после проверки валидности.
При работе с пользовательскими данными основная стратегия основана на жёсткой проверке:
const m = moment(userInput, "YYYY-MM-DD", true);
if (!m.isValid()) {
// отклонение ввода
}
Дополнительные проверки часто включают:
isValid() обязательна после каждого создания
объектаparsingFlags() используется для диагностики причин
ошибки