Переопределение поведения в Luxon опирается на несколько уровней абстракции: глобальные настройки (Settings), механизм временных зон (Zone), локализация (locale), а также точечное управление через методы DateTime. Архитектура библиотеки построена так, чтобы базовые сущности оставались неизменяемыми, а изменение поведения происходило через конфигурацию и подмену зависимостей, а не через мутацию объектов.
Центральный механизм изменения поведения — объект Settings. Он задаёт параметры по умолчанию для всех создаваемых экземпляров DateTime.
Поведение всех операций с датой и временем зависит от выбранной зоны. Если зона не указана явно, используется Settings.defaultZone:
import { Settings } from "luxon";
Settings.defaultZone = "Europe/Paris";
После этого любой вызов создания даты без явного указания зоны будет интерпретироваться в указанной временной зоне.
В качестве значения могут использоваться:
"Europe/Moscow",
"UTC")Локаль влияет на форматирование дат, названия месяцев, дней недели и поведение Intl:
Settings.defaultLocale = "ru";
Это влияет на:
toLocaleString()toFormat()Info (например, названия месяцев)Luxon позволяет заменить источник времени, что критично для тестирования и моделирования:
Settings.now = () => 1700000000000;
Теперь DateTime.now() всегда будет возвращать
фиксированное значение.
Такой подход позволяет:
Settings.throwOnInvalid = true;
При включении любое некорректное создание DateTime приводит к выбросу исключения вместо возврата объекта с состоянием invalid. Это изменяет модель обработки ошибок с «мягкой» на «строгую».
Luxon построен вокруг абстракции Zone. Именно через неё достигается переопределение поведения интерпретации времени.
Внутри используются стандартные реализации:
DateTime.fromMillis(0, { zone: "UTC" });
DateTime.fromObject({ year: 2025 }, { zone: "Europe/Berlin" });
Каждый объект DateTime хранит свою зону, что делает экземпляры независимыми от глобальной конфигурации.
Механизм расширения поведения через зоны основан на контракте Zone. Пользовательская зона должна реализовывать интерфейс:
typenameoffsetName(ts)formatOffset(ts, format)offset(ts)equals(otherZone)isValidПример концептуальной реализации:
class CustomZone {
constructor(offsetMinutes) {
this._offset = offsetMinutes;
}
get type() {
return "custom";
}
get name() {
return `UTC+${this._offset}`;
}
offset(ts) {
return this._offset;
}
offsetName() {
return this.name;
}
formatOffset() {
return this.name;
}
equals(other) {
return other && other.offset === this._offset;
}
get isValid() {
return true;
}
}
Использование такой зоны позволяет полностью переопределить логику интерпретации времени, включая смещение и форматирование.
Luxon не позволяет изменять внутреннюю реализацию DateTime, но предоставляет множество точек контроля через фабричные методы.
DateTime.fromMillis(1620000000000, { zone: "UTC" });
DateTime.fromSeconds(1620000000, { zone: "local" });
Эти методы определяют:
Наиболее гибкий способ создания даты:
DateTime.fromObject(
{ year: 2025, month: 1, day: 1, hour: 10 },
{ zone: "Europe/Moscow", locale: "ru" }
);
Здесь переопределяется сразу несколько аспектов поведения:
Каждый DateTime является неизменяемым, но позволяет создавать производные объекты с изменённым поведением.
dt.setZone("Asia/Tokyo");
Меняется только интерпретация времени, без изменения абсолютного момента.
dt.setLocale("en");
Изменяет форматирование без влияния на значение времени.
Метод set позволяет точечно переопределять части
состояния:
dt.set({ zone: "UTC", locale: "fr" });
Поведение форматирования зависит от Intl API и внутренних правил Luxon.
dt.toFormat("yyyy LLL dd");
Формат зависит от:
Изменение Settings.defaultLocale или instance locale приводит к изменению результата без изменения кода форматирования.
dt.toLocaleString(DateTime.DATETIME_FULL);
Поведение этого метода полностью зависит от Intl, но может быть переопределено через глобальные настройки среды выполнения (Intl.NumberFormat, Intl.DateTimeFormat).
Ключевой механизм тестируемости — Settings.now.
Settings.now = () => Date.UTC(2030, 0, 1);
Любые вызовы:
будут возвращать фиксированную точку отсчёта.
Это влияет на:
Методы diff и plus/minus зависят от текущей конфигурации зоны и локали.
dt.plus({ days: 1 });
dt.minus({ hours: 5 });
Переопределение зоны влияет на результат, поскольку:
Luxon поддерживает альтернативные календари через Intl (частично).
Settings.defaultOutputCalendar = "islamic";
Это влияет на:
Хотя внутренняя модель времени остаётся григорианской, визуальное представление может быть изменено.
Прямое наследование DateTime не предусмотрено как основной путь расширения, поэтому используется композиция.
function CustomDateTime(dt) {
return {
original: dt,
toString() {
return `[CUSTOM] ${dt.toISO()}`;
}
};
}
Такой подход позволяет:
Все цепочки DateTime наследуют текущие Settings в момент создания экземпляра.
Settings.defaultZone = "UTC";
const a = DateTime.now();
Settings.defaultZone = "Asia/Tokyo";
const b = DateTime.now();
a использует UTCb использует Asia/TokyoЭто демонстрирует, что поведение фиксируется на момент инстанцирования, а не вычисляется динамически.
В сложных приложениях поведение Luxon часто разделяется на контексты:
Luxon позволяет моделировать такие сценарии через:
Каждый уровень переопределяет поведение независимо, формируя многослойную модель управления временем.