В библиотеке Luxon любой результат работы с датами, интервалами и длительностями может находиться в состоянии валидности или невалидности. Это ключевой механизм защиты от некорректных вычислений: вместо выброса исключений большинство методов возвращают объект, который явно помечен как невалидный.
Невалидный объект — это экземпляр DateTime,
Duration или Interval, который не смог быть
корректно создан или преобразован из входных данных. При этом он
сохраняет интерфейс объекта библиотеки, но любые операции над ним либо
возвращают другие невалидные объекты, либо становятся
бессмысленными.
Наиболее частый источник проблем — неверный формат входной строки.
import { DateTime } from "luxon";
const dt = DateTime.fromISO("2026-13-40");
console.log(dt.isValid); // false
Здесь строка не соответствует ISO-формату: месяц 13 и день 40 не существуют.
fromFormatПри ручном разборе дат через шаблон ошибки возникают особенно часто:
const dt = DateTime.fromFormat("31/02/2026", "dd/MM/yyyy");
console.log(dt.isValid); // false
console.log(dt.invalidReason); // 'unparsable'
Даже если строка формально соответствует шаблону, логическая корректность (например, существование 31 февраля) всё равно проверяется.
Некорректное имя зоны приводит к невалидности:
const dt = DateTime.now().setZone("Mars/Phobos");
console.log(dt.isValid); // false
console.log(dt.invalidReason); // 'unsupported zone'
Luxon опирается на IANA Time Zone Database, и любое отклонение от допустимых значений делает объект невалидным.
const dt = DateTime.fromObject({
year: 2026,
month: 2,
day: 30
});
console.log(dt.isValid); // false
Любые невозможные календарные комбинации приводят к невалидному результату.
Главный индикатор состояния объекта:
if (!dt.isValid) {
// объект нельзя использовать для вычислений
}
Это первое, что проверяется перед любыми операциями.
Строковое описание причины:
"unparsable" — строка не распознана"unit out of range" — значение выходит за допустимые
пределы"unsupported zone" — таймзона не существует"invalid input" — общий случай некорректных данныхconsole.log(dt.invalidReason);
Более подробное объяснение причины, часто полезное при отладке:
console.log(dt.invalidExplanation);
Пример вывода может содержать указание на конкретный компонент, который вызвал сбой.
Любая операция над невалидным объектом сохраняет его невалидность.
const dt = DateTime.fromISO("invalid-date");
const shifted = dt.plus({ days: 5 });
console.log(shifted.isValid); // false
Библиотека не пытается «исправлять» уже сломанные данные.
Аналогичная модель применяется к длительностям:
import { Duration } from "luxon";
const d = Duration.fromObject({ hours: "ten" });
console.log(d.isValid); // false
console.log(d.invalidReason); // 'invalid input'
Любые нечисловые значения приводят к невалидности.
Интервалы требуют корректных границ:
import { Interval, DateTime } from "luxon";
const start = DateTime.fromISO("2026-01-10");
const end = DateTime.fromISO("2026-01-01");
const interval = Interval.fromDateTimes(start, end);
console.log(interval.isValid); // false
Если начало позже конца — объект считается некорректным.
Невалидность распространяется по цепочке вычислений:
const dt = DateTime.fromISO("invalid")
.setZone("UTC")
.plus({ days: 1 })
.setLocale("ru");
console.log(dt.isValid); // false
Даже если последующие методы корректны, исходная ошибка делает весь результат невалидным.
Форматирование не исправляет ошибки:
const dt = DateTime.fromISO("bad input");
console.log(dt.toISO()); // null
console.log(dt.toString()); // "Invalid DateTime"
Без проверки isValid можно получить неожиданные строки
или null.
const dt = DateTime.fromISO(apiResponse.date);
if (!dt.isValid) {
// защита от некорректного сервера
}
const dt = DateTime.fromFormat(userInput, "dd.MM.yyyy");
if (!dt.isValid) {
console.log(dt.invalidExplanation);
}
const dt = DateTime.fromISO("2026/01/01"); // неверный ISO
console.log(dt.isValid); // false
function safeFormat(dt) {
if (!dt.isValid) return "Некорректная дата";
return dt.toFormat("dd LLL yyyy");
}
const dt = DateTime.fromISO(input);
const safe = dt.isValid ? dt : DateTime.now();
if (!dt.isValid) {
console.error(dt.invalidReason, dt.invalidExplanation);
}
Невалидные объекты при преобразовании в JSON теряют полезные данные:
const dt = DateTime.fromISO("bad");
console.log(JSON.stringify(dt));
// {}
Это связано с тем, что внутреннее состояние считается недостоверным.
Luxon не использует исключения для большинства ошибок парсинга. Это делает API предсказуемым:
try/catch для обычного
парсингаisValidНекорректные локали обычно не делают объект невалидным, но могут приводить к неожиданным форматам. Таймзоны же строго валидируются:
const dt = DateTime.now().setZone("invalid-zone");
console.log(dt.isValid); // false
Устойчивый шаблон работы:
const dt = DateTime.fromISO(input);
if (!dt.isValid) {
return handleError(dt.invalidReason);
}
return dt.toUTC().toISO();
toISO() без проверки
isValidinvalidReasonconst dt = DateTime.fromISO("invalid")
.toUTC()
.set({ hour: 10 });
console.log(dt.isValid); // false
Любые преобразования не восстанавливают корректность объекта, так как исходная структура уже признана недостоверной.
При работе с цепочками преобразований важна централизованная проверка:
function transformDate(input) {
const dt = DateTime.fromISO(input);
if (!dt.isValid) return null;
return dt
.setZone("UTC")
.startOf("day")
.toISO();
}
Такой подход предотвращает распространение невалидных объектов по системе.