Проверка валидности

В библиотеке Luxon работа с датами и временем строится вокруг иммутабельных объектов, которые могут находиться в двух состояниях: корректном и некорректном. В отличие от встроенного объекта Date, где некорректная дата часто «маскируется» под валидное значение Invalid Date, Luxon явно фиксирует состояние валидности через внутренние флаги и свойства.

Каждый экземпляр DateTime и Duration содержит встроенную информацию о том, может ли он считаться корректным результатом вычисления или парсинга. Это позволяет выстраивать предсказуемую модель обработки ошибок без исключений.


Основной механизм проверки: DateTime.isValid

Ключевым инструментом проверки является свойство:

  • DateTime.isValid

Оно возвращает булево значение:

  • true — объект корректен и может использоваться в операциях
  • false — объект содержит ошибку и считается невалидным

Пример логики:

import { DateTime } from "luxon";

const dt1 = DateTime.now();
console.log(dt1.isValid); // true

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

const dt2 = DateTime.fromISO("2024-13-40");
console.log(dt2.isValid); // false

Luxon не выбрасывает исключения при ошибках парсинга — вместо этого создаёт объект с флагом невалидности.


Причины невалидности: invalidReason и invalidExplanation

Для диагностики ошибок используются два свойства:

  • invalidReason — краткий код причины
  • invalidExplanation — человекочитаемое описание

Пример:

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

console.log(dt.isValid); // false
console.log(dt.invalidReason); // 'unparsable'
console.log(dt.invalidExplanation); // 'the input could not be parsed as a valid ISO date'

Типовые значения invalidReason

Чаще всего встречаются:

  • unparsable — строка не может быть распознана
  • invalid input — переданы некорректные аргументы
  • unsupported zone — неподдерживаемая временная зона
  • missing field — отсутствуют обязательные поля
  • out of range — значение выходит за допустимые границы

Эти причины позволяют быстро классифицировать ошибку без дополнительного анализа входных данных.


Точки возникновения невалидных DateTime

Парсинг ISO-строк

DateTime.fromISO("2025-02-30");

Февраль не содержит 30 дней, поэтому результат будет невалидным.

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

dt.isValid; // false

Конструкторы с объектами

DateTime.fromObject({
  year: 2024,
  month: 13,
  day: 10
});

Здесь month: 13 выходит за пределы допустимого диапазона.


Форматированный парсинг fromFormat

DateTime.fromFormat("31-02-2024", "dd-MM-yyyy");

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


JavaScript Date как источник

DateTime.fromJSDate(new Date("invalid date"));

Если исходный Date невалиден, Luxon наследует это состояние.


Строгий парсинг и влияние форматов

Методы парсинга в Luxon зависят от строгости формата.

ISO-парсинг

fromISO предполагает строгий формат ISO-8601. Любые отклонения приводят к isValid = false.

DateTime.fromISO("2024/01/01"); // невалидно

Форматированный парсинг

fromFormat зависит от маски:

DateTime.fromFormat("2024-01-01", "dd/MM/yyyy");

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


Жёсткость и опции

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

DateTime.fromFormat("32/01/2024", "dd/MM/yyyy", { lenient: true });

Однако даже в «мягком» режиме логически невозможные даты всё равно могут стать причиной невалидного объекта.


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

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

Месяцы

  • допустимые значения: 1–12

Дни

  • зависят от месяца и года (учёт високосных лет)

Часы и минуты

  • часы: 0–23
  • минуты: 0–59
  • секунды: 0–59

Пример переполнения:

DateTime.fromObject({
  year: 2024,
  month: 1,
  day: 1,
  hour: 25
});

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


Валидность временных зон

Luxon активно использует IANA Time Zone Database.

Проверка зоны

DateTime.fromObject(
  { zone: "Europe/InvalidCity" }
);

Если зона не существует:

  • isValid = false
  • invalidReason = "unsupported zone"

Примеры корректных зон:

  • UTC
  • Europe/Berlin
  • Asia/Almaty

Duration и валидность

Помимо DateTime, объект Duration также поддерживает проверку валидности.

import { Duration } from "luxon";

const d = Duration.fromObject({ hours: 2, minutes: -10 });
console.log(d.isValid);

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

  • некорректные типы данных
  • переполнение внутренних значений

Безопасная работа с невалидными объектами

Любая операция с DateTime потенциально может вернуть невалидный результат:

const result = DateTime.fromISO("2024-02-30").plus({ days: 1 });

Если исходный объект невалиден:

result.isValid; // false

Luxon не «чинит» невалидные даты автоматически — цепочка операций сохраняет состояние ошибки.


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

Базовая проверка

if (!dt.isValid) {
  // обработка ошибки
}

Проверка с диагностикой

if (!dt.isValid) {
  console.log(dt.invalidReason);
  console.log(dt.invalidExplanation);
}

Защитное преобразование

const safeDate = dt.isValid ? dt : DateTime.now();

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

Любая цепочка методов сохраняет невалидность:

const dt = DateTime.fromISO("invalid")
  .plus({ days: 2 })
  .set({ year: 2025 });

console.log(dt.isValid); // false

Даже если последующие операции корректны, исходная ошибка «приклеивается» к объекту.


Отличие от встроенного Date

В JavaScript Date:

new Date("invalid"); // Invalid Date

Особенности:

  • не содержит явного isValid
  • проверка осуществляется через isNaN(date.getTime())

Luxon:

  • предоставляет явное поле isValid
  • сохраняет причину ошибки
  • не требует дополнительных вычислений

Сценарии типичных ошибок и их интерпретация

Ошибка парсинга строки

DateTime.fromISO("2024-99-99")
  • причина: unparsable
  • объяснение: строка не соответствует ISO

Ошибка временной зоны

DateTime.now().setZone("Mars/Phobos");
  • причина: unsupported zone

Ошибка формата

DateTime.fromFormat("2024-01-01", "MM-dd-yyyy");
  • причина: unparsable

Влияние локали на валидность

Некоторые методы зависят от локали при разборе форматов:

DateTime.fromFormat("31/01/2024", "dd/MM/yyyy", { locale: "en" });

Неправильное соответствие локали и формата может привести к невалидности, особенно при неоднозначных датах.


Валидация после арифметических операций

Luxon допускает арифметику над датами:

const dt = DateTime.now().plus({ months: 1 });

Однако:

  • если исходный объект невалиден — результат остаётся невалидным
  • переполнение редко приводит к исключениям, но может приводить к невалидным результатам при некорректных входных данных

Проверка границ при создании объектов

При создании через fromObject важно учитывать:

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

Пример:

DateTime.fromObject({
  year: "2024",
  month: "февраль",
  day: null
});

Результат:

  • isValid = false
  • причина: invalid input

Обработка невалидных значений в потоках данных

При работе с внешними API часто встречаются некорректные даты:

const apiDate = "2024-02-30T10:00:00Z";

const dt = DateTime.fromISO(apiDate);

if (!dt.isValid) {
  // фильтрация или замена значения
}

Luxon позволяет централизованно фильтровать некорректные данные без исключений и try/catch конструкций.


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

Невалидный объект распространяет своё состояние:

const a = DateTime.fromISO("invalid");
const b = DateTime.now();

const c = a > b; // некорректное сравнение

Такие операции не имеют смысла и требуют предварительной проверки isValid.


Особенности сериализации

При вызове:

JSON.stringify(DateTime.now())

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

dt.isValid ? dt.toISO() : null;

Роль валидности в архитектуре обработки времени

Модель Luxon предполагает:

  • создание объектов без исключений
  • перенос ошибок в состояние объекта
  • явную проверку isValid перед использованием

Это делает обработку дат детерминированной и предсказуемой даже при некорректных входных данных.