В библиотеке Luxon ключевая концепция обработки ошибок в датах основана не на выбросе исключений, а на распространении состояния невалидности через цепочку вычислений.
Объект считается невалидным, если его невозможно корректно
интерпретировать как дату/время или интервал. В таком случае он получает
внутренний флаг состояния isValid = false и сопровождающее
описание причины в invalidReason.
Типичные причины появления невалидного объекта:
fromISO,
fromFormat)Ключевое правило: если объект невалиден, все производные операции возвращают невалидный результат
Это означает, что большинство методов Luxon не выбрасывают исключения, а возвращают новый невалидный объект того же типа.
Пример:
import { DateTime } from "luxon";
const dt = DateTime.fromISO("invalid-date");
console.log(dt.isValid); // false
const updated = dt.plus({ days: 5 });
console.log(updated.isValid); // false
Метод plus() не пытается “исправить” исходное значение —
он лишь сохраняет цепочку невалидности.
Методы plus() и minus() полностью
игнорируют попытки нормализации данных, если исходный объект
невалиден.
const dt = DateTime.fromISO("not-a-date");
const result = dt.plus({ hours: 3 });
console.log(result.isValid); // false
Если же объект валиден, но переданы некорректные аргументы, результат также становится невалидным:
const dt = DateTime.now();
const result = dt.plus({ hours: "abc" });
console.log(result.isValid); // false
Методы, изменяющие точность даты, также подчиняются правилу распространения:
const dt = DateTime.invalid("custom reason");
console.log(dt.startOf("day").isValid); // false
При попытке форматирования невалидного объекта возвращается строка-индикатор:
const dt = DateTime.fromISO("broken");
console.log(dt.toISO());
// null или "Invalid DateTime" (в зависимости от метода)
Типичное поведение:
toISO() → nulltoString() → "Invalid DateTime"toFormat() → "Invalid DateTime"Метод toFormat не пытается интерпретировать данные:
const dt = DateTime.invalid("parse error");
console.log(dt.toFormat("yyyy LLL dd"));
// Invalid DateTime
Форматирование не выполняется даже частично.
При обращении к компонентам даты (год, месяц, день) поведение зависит от внутренней реализации:
const dt = DateTime.fromISO("invalid");
console.log(dt.year); // NaN или undefined (зависит от контекста)
Однако гарантированное поведение:
isValid всегда falseinvalidReason содержит причинуinvalidExplanation может содержать расширенное
описаниеconsole.log(dt.invalidReason);
// "unparsable" / "invalid input" / "unsupported zone" и т.д.
Любые операции сравнения с невалидными объектами дают предсказуемо отрицательный результат:
const a = DateTime.invalid("a");
const b = DateTime.now();
console.log(a < b); // false
console.log(a > b); // false
При этом сравнение двух невалидных объектов также не даёт значимого результата:
const a = DateTime.invalid("a");
const b = DateTime.invalid("b");
console.log(a.equals(b)); // false
Метод equals() требует валидности обоих объектов.
Метод equals() строго проверяет корректность:
const dt = DateTime.invalid("x");
console.log(dt.equals(DateTime.now())); // false
Если один из объектов невалиден — результат всегда
false.
При попытке конвертации в нативный объект Jav * aScript:
const dt = DateTime.invalid("error");
console.log(dt.toJSDate());
// Invalid Date (Date object)
Возвращается объект Date, но содержащий значение
Invalid Date. Это важно:
Аналогичный механизм распространяется на Duration.
import { Duration } from "luxon";
const d = Duration.fromObject({ hours: "x" });
console.log(d.isValid); // false
Любые операции:
const d2 = d.plus({ minutes: 10 });
console.log(d2.isValid); // false
Interval становится невалидным, если хотя бы одна
граница некорректна:
import { Interval, DateTime } from "luxon";
const start = DateTime.invalid("bad");
const end = DateTime.now();
const interval = Interval.fromDateTimes(start, end);
console.log(interval.isValid); // false
Все методы интервала наследуют это состояние:
console.log(interval.length()); // NaN
console.log(interval.toISO()); // null или "Invalid Interval"
Одно из ключевых свойств Luxon — неизменяемость объектов. В связке с невалидностью это приводит к строгому правилу:
один невалидный шаг делает всю цепочку невалидной
const result = DateTime
.fromISO("bad-date")
.setZone("UTC")
.plus({ days: 1 })
.toFormat("yyyy-MM-dd");
console.log(result);
// Invalid DateTime
Даже если последующие операции корректны, они не выполняются.
Основной индикатор состояния:
const dt = DateTime.fromISO("2020-01-01");
console.log(dt.isValid); // true
Код причины:
unparsableinvalid inputunsupported zoneout of rangeconflicting configurationconst dt = DateTime.fromISO("2020-99-99");
console.log(dt.invalidReason);
Человекочитаемое описание:
console.log(dt.invalidExplanation);
// более подробное объяснение ошибки
При преобразовании в JSON:
const dt = DateTime.invalid("error");
console.log(JSON.stringify(dt));
Результат обычно:
nullВажно: сериализация не “исправляет” данные.
Локализованные методы (toLocaleString,
toLocaleParts) также подчиняются правилу невалидности:
const dt = DateTime.invalid("bad");
console.log(dt.toLocaleString());
// "Invalid DateTime"
Поведение невалидных объектов в Luxon строится на трёх принципах:
Это обеспечивает предсказуемость:
isValidconst dt = DateTime.fromISO(userInput);
console.log(dt.toFormat("yyyy")); // риск "Invalid DateTime"
const result = DateTime.fromISO(input)
.plus({ days: 1 })
.toISO();
При некорректном input результат будет null
или строкой ошибки.
Luxon не поддерживает “частично корректные” даты:
Поведение методов на невалидных объектах в Luxon сводится к единому правилу:
любой метод, получивший невалидный объект, возвращает невалидный объект того же типа без попытки исправления данных
Это делает систему детерминированной и упрощает построение цепочек вычислений без скрытых преобразований и неожиданных побочных эффектов.