Одной из наиболее частых ошибок при работе с Luxon становится
игнорирование иммутабельности объектов DateTime. Любая
операция, изменяющая дату или время, не модифицирует исходный объект, а
возвращает новый экземпляр.
Типичная ошибка проявляется при цепочках вызовов:
let dt = DateTime.now();
dt.plus({ days: 2 });
dt.minus({ hours: 3 });
console.log(dt.toString());
В результате выводится исходное значение, поскольку результаты
plus и minus были проигнорированы. Правильный
подход требует явного сохранения возвращаемого значения:
let dt = DateTime.now()
.plus({ days: 2 })
.minus({ hours: 3 });
Игнорирование этого принципа приводит к ошибкам в вычислениях сроков, дедлайнов и временных интервалов, особенно в цепочках преобразований.
Luxon строго разделяет локальное время и время в конкретной зоне. Ошибка возникает при предположении, что установка зоны изменяет момент времени.
const dt = DateTime.fromISO("2024-01-01T10:00", { zone: "utc" });
const shifted = dt.setZone("Asia/Almaty");
setZone не изменяет момент времени, а лишь отображение.
Это означает, что 10:00 UTC станет другим локальным временем в новой
зоне, но момент времени останется тем же.
Частая ошибка — ожидание смещения времени как арифметической операции:
dt.setZone("Asia/Almaty").hour // не "пересчитывает" время как прибавление смещения
Для реального изменения момента времени используется конвертация через UTC или корректная интерпретация входных данных.
Luxon разделяет три сущности:
DateTime — точка во времениDuration — длительностьInterval — промежуток между двумя точкамиРаспространённая ошибка — использование Duration как
DateTime:
const d = Duration.fromObject({ hours: 2 });
console.log(d.plus({ hours: 1 }));
Хотя это допустимо, результат остаётся длительностью, а не временем.
Ещё более критичная ошибка — попытка сравнивать Interval
как дату:
const i = Interval.fromDateTimes(dt1, dt2);
console.log(i > DateTime.now());
Сравнение не имеет смысла и приводит к логическим сбоям. Правильный
подход — использовать методы overlaps,
contains, isAfter, isBefore.
Luxon строго различает методы парсинга. Частая ошибка — использование
fromISO для не-ISO строк:
DateTime.fromISO("01-02-2024");
Такая строка не соответствует ISO-формату и вернёт
Invalid DateTime.
Для произвольных форматов требуется fromFormat:
DateTime.fromFormat("01-02-2024", "dd-MM-yyyy");
Ошибка в маске форматирования приводит к тихой невалидности объекта, что часто не проверяется:
const dt = DateTime.fromFormat("2024/01/01", "dd-MM-yyyy");
console.log(dt.isValid); // false
Игнорирование isValid — одна из самых распространённых
причин скрытых багов.
Каждый объект Luxon может оказаться невалидным. Ошибка часто возникает при цепочках:
const dt = DateTime.fromFormat(input, "yyyy-MM-dd")
.plus({ days: 1 });
Если input некорректен, дальнейшие операции сохраняют
невалидное состояние.
Правильная практика — проверка после парсинга:
const dt = DateTime.fromFormat(input, "yyyy-MM-dd");
if (!dt.isValid) {
// обработка ошибки
}
Отсутствие проверки приводит к распространению
Invalid DateTime по всей логике приложения.
Метод toFormat использует собственный синтаксис токенов,
отличный от Intl и Moment.js. Частая ошибка — использование
неправильных символов:
dt.toFormat("YYYY-MM-DD"); // неправильно
В Luxon корректный вариант:
dt.toFormat("yyyy-MM-dd");
Различие между yyyy и YYYY критично: первое
— календарный год, второе — ISO-неделя, что приводит к ошибкам в конце
года.
Метод toLocaleString опирается на встроенные пресеты, и
попытка передать кастомный формат приводит к неожиданным
результатам:
dt.toLocaleString(DateTime.DATE_HUGE);
Ошибка возникает при ожидании полного контроля над форматом. Этот метод предназначен только для стандартных шаблонов.
Для точного форматирования необходимо использовать
toFormat.
При конвертации через toJSDate теряется информация о
временной зоне Luxon:
const jsDate = dt.toJSDate();
Date хранит момент времени в UTC, но не сохраняет
оригинальную зону Luxon. При обратном преобразовании зона не
восстанавливается:
DateTime.fromJSDate(jsDate).zoneName; // системная зона
Это приводит к ошибкам при многозонной логике.
Частая ошибка — смешивание local и utc без
явного контроля:
const dt = DateTime.local().toUTC();
Здесь происходит корректное преобразование, но обратная операция часто выполняется неправильно:
dt.toLocal(); // зависит от системной зоны
В распределённых системах это приводит к различиям между окружениями.
Методы startOf и endOf возвращают новые
объекты, а также изменяют только указанный уровень точности.
Ошибка возникает при ожидании полного «обнуления» времени:
dt.startOf("day");
Результат будет иметь 00:00, но зона и момент времени сохраняются.
Частая проблема — сравнение таких значений без учёта зоны:
dt.startOf("day") === otherDate.startOf("day");
Сравнение объектов всегда по ссылке, а не по значению.
Luxon допускает сложение объектов, но неправильное использование приводит к логическим дефектам:
DateTime.now().plus({ months: 1, days: 30 });
Месяцы и дни не эквивалентны по длительности, что вызывает неожиданные результаты в разных календарных системах.
Некорректные строки зон не всегда вызывают очевидную ошибку:
DateTime.now().setZone("Asia/Alma-Ata");
Если идентификатор не поддерживается, Luxon может вернуть невалидное состояние или fallback-зону. Это особенно критично при миграции между библиотеками и базами данных.
Luxon хранит время с точностью до миллисекунд, но форматирование может скрывать эту точность:
dt.toFormat("HH:mm:ss");
Миллисекунды теряются визуально, но сохраняются в объекте, что приводит к расхождению при сравнении:
dt1.equals(dt2); // может быть false при одинаковом отображении
Часто DateTime сериализуют напрямую:
JSON.stringify(dt);
Результат не содержит полезной структуры Luxon. Правильный подход — явное преобразование:
dt.toISO();
Игнорирование этого приводит к потере зоны, точности и контекста времени при передаче между сервисами.