Валидация пользовательского ввода

Работа с датами и временем в прикладных JavaScript-системах почти всегда связана с внешними источниками данных: формы, API, CSV-файлы, пользовательские настройки. Любой входной формат представляет потенциально некорректную строку, поэтому этап валидации становится обязательной частью обработки.

Библиотека Luxon рассматривает результат парсинга как объект, который может находиться в двух состояниях: корректном и некорректном. Это состояние определяется сразу после попытки создания даты.

Основной принцип: любой разбор входной строки возвращает объект DateTime, даже если данные не соответствуют ожидаемому формату.


Механизм создания объектов DateTime и роль валидности

При создании даты через Luxon используются статические методы:

  • DateTime.fromISO
  • DateTime.fromFormat
  • DateTime.fromJSDate
  • DateTime.fromRFC2822
  • DateTime.fromHTTP

Каждый из этих методов возвращает экземпляр DateTime, содержащий флаг валидности.

import { DateTime } from "luxon";

const dt = DateTime.fromISO("2025-13-40");

console.log(dt.isValid);
console.log(dt.invalidReason);
console.log(dt.invalidExplanation);

Ключевые свойства:

  • isValid — булево значение корректности результата
  • invalidReason — краткий код ошибки
  • invalidExplanation — текстовое пояснение

Любая операция с некорректным объектом сохраняет его состояние, не выбрасывая исключение.


Основные источники некорректного ввода

Нарушение формата ISO

ISO 8601 является наиболее строгим форматом. Ошибки возникают при:

  • выходе месяца за диапазон 1–12
  • неправильной длине компонентов
  • нарушении структуры строки
DateTime.fromISO("2024-99-10").isValid; // false

Несоответствие кастомному формату

Метод fromFormat требует строгого соответствия шаблону.

const dt = DateTime.fromFormat("31/02/2025", "dd/MM/yyyy");

dt.isValid; // false

Причина: 31 февраля не существует.


Несоответствие типов входных данных

Luxon ожидает строки, числа или объекты Date. Передача произвольных значений приводит к ошибке.

DateTime.fromISO(null).isValid; // false
DateTime.fromJSDate("not a date").isValid; // false

Использование флага isValid как механизма контроля

Валидация в Luxon не строится на исключениях. Контроль выполняется через проверку состояния объекта.

const dt = DateTime.fromISO(userInput);

if (!dt.isValid) {
  // обработка некорректного значения
}

Такой подход позволяет:

  • обрабатывать ошибки без try/catch
  • сохранять поток выполнения
  • централизовать обработку некорректных данных

Разбор invalidReason и классификация ошибок

Свойство invalidReason возвращает код, описывающий тип проблемы:

  • unparsable — невозможность разобрать строку
  • invalid input — неподходящий тип данных
  • out of range — значение вне допустимого диапазона
  • unit out of range — ошибка в единицах времени

Пример анализа:

const dt = DateTime.fromISO("2024-02-30");

if (!dt.isValid) {
  switch (dt.invalidReason) {
    case "out of range":
      // дата не существует
      break;
  }
}

Расширенная диагностика через invalidExplanation

Свойство invalidExplanation формирует человекочитаемое описание.

const dt = DateTime.fromFormat("31/11/2024", "dd/MM/yyyy");

console.log(dt.invalidExplanation);

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


Валидация при работе с пользовательскими форматами

Форматы, основанные на fromFormat, требуют строгого описания шаблона:

const format = "yyyy-MM-dd HH:mm";
const input = "2025-06-31 14:20";

const dt = DateTime.fromFormat(input, format);

if (!dt.isValid) {
  // дата 31 июня не существует
}

Особенность: Luxon не исправляет данные автоматически, даже если часть строки корректна.


Поведение при частично корректных данных

Входные строки, содержащие корректные и некорректные сегменты, полностью считаются ошибочными.

DateTime.fromISO("2025-05-10T25:00").isValid; // false

Причина: час выходит за пределы 0–23.


Валидация временных зон

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

const dt = DateTime.fromISO("2025-05-10T10:00", {
  zone: "Invalid/Zone"
});

dt.isValid; // false

Ошибки зон включают:

  • несуществующие идентификаторы
  • конфликт локального времени
  • некорректные правила перехода

Проверка цепочек преобразований

Luxon сохраняет валидность через цепочку операций.

const dt = DateTime
  .fromISO("2025-05-10")
  .plus({ days: 5 })
  .minus({ months: 2 });

dt.isValid;

Если исходное значение некорректно, последующие операции не исправляют его состояние.


Валидация после преобразования в JS Date

Конвертация из стандартного объекта Date также требует проверки:

const jsDate = new Date("invalid");

const dt = DateTime.fromJSDate(jsDate);

dt.isValid; // false

Любая некорректная дата JavaScript автоматически транслируется в невалидный DateTime.


Стратегии фильтрации входных данных

При обработке массивов входных дат используется явная фильтрация:

const inputs = [
  "2025-01-10",
  "2025-99-99",
  "2025-03-15"
];

const validDates = inputs
  .map(i => DateTime.fromISO(i))
  .filter(dt => dt.isValid);

Результат содержит только корректные объекты.


Сравнение валидных и невалидных объектов

Невалидный DateTime сохраняет интерфейс объекта, но не участвует в корректных вычислениях:

  • арифметика дат возвращает невалидный результат
  • форматирование возвращает строку "Invalid DateTime"
const dt = DateTime.fromISO("invalid");

console.log(dt.toString()); // Invalid DateTime

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

При преобразовании в JSON невалидные объекты теряют смысловое значение:

JSON.stringify(DateTime.fromISO("invalid"));
// {}

Рекомендуется предварительная проверка isValid перед сериализацией.


Контроль входных данных в API-слое

При приёме данных из внешних источников применяется двухэтапная схема:

  1. первичное преобразование в DateTime
  2. проверка isValid
  3. дальнейшая обработка только корректных объектов
function parseDate(input) {
  const dt = DateTime.fromISO(input);

  if (!dt.isValid) return null;

  return dt;
}

Обработка ошибок валидации в сложных сценариях

При агрегации временных данных важно учитывать распространение невалидности:

const start = DateTime.fromISO("2025-01-10");
const end = DateTime.fromISO("invalid");

const diff = end.diff(start);

diff.isValid; // false

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


Особенности работы с локалями и форматами отображения

Некорректный ввод может быть связан с локализацией:

DateTime.fromFormat("10.05.2025", "MM/dd/yyyy").isValid; // false

Несовпадение формата и локального представления даты является частым источником ошибок.


Роль строгого парсинга в предсказуемости системы

Модель обработки данных в Luxon исключает автоматическое исправление ошибок. Любое отклонение от формата приводит к фиксированному состоянию невалидности.

Это обеспечивает:

  • детерминированность обработки
  • прозрачную диагностику ошибок
  • отсутствие скрытых преобразований