Длительность в Luxon представляет собой абстракцию временного промежутка, независимого от конкретных дат и календарей. Она описывает не точку во времени, а количество времени в различных единицах: миллисекундах, секундах, минутах, часах, днях и так далее. Такой подход позволяет работать с временными интервалами как с математическими объектами, выполняя над ними преобразования, сложение, вычитание и нормализацию.
В основе лежит объект Duration, который инкапсулирует набор единиц времени и предоставляет инструменты для их преобразования и вычислений.
Наиболее распространённый способ создания длительности — через объект с указанием временных единиц:
import { Duration } from "luxon";
const d = Duration.fromObject({
hours: 2,
minutes: 30,
seconds: 15
});
Такой объект не выполняет автоматическую нормализацию: значения сохраняются в заданных единицах, пока не применяется явное преобразование.
Для работы с низкоуровневым представлением времени используется метод
fromMillis:
const d = Duration.fromMillis(9000000);
Значение интерпретируется как количество миллисекунд, которое затем может быть преобразовано в более удобные единицы.
Luxon поддерживает стандарт ISO 8601 для представления длительностей:
const d = Duration.fromISO("PT2H30M15S");
Формат:
P — префикс периодаT — разделитель даты и времениH, M, S — часы, минуты,
секундыОбъект Duration хранит данные в виде набора единиц, например:
{
hours: 2,
minutes: 30,
seconds: 15
}
При этом Luxon не всегда автоматически приводит значения к единому масштабу. Например, 90 минут не будут автоматически преобразованы в 1 час 30 минут без вызова нормализации.
Нормализация приводит значения к стандартному виду, перераспределяя избыточные единицы:
const d = Duration.fromObject({
hours: 1,
minutes: 90
}).normalize();
Результат:
2 hours, 30 minutes
Метод normalize важен при вычислениях, где возможны
переполнения единиц (например, секунды → минуты → часы).
Длительности можно складывать:
const d1 = Duration.fromObject({ hours: 1 });
const d2 = Duration.fromObject({ minutes: 30 });
const sum = d1.plus(d2);
Результат сохраняет структуру единиц, при необходимости требуется нормализация.
const d1 = Duration.fromObject({ hours: 2 });
const d2 = Duration.fromObject({ minutes: 45 });
const diff = d1.minus(d2);
Результат может содержать отрицательные значения в отдельных единицах, если не выполнена нормализация.
Длительность может масштабироваться:
const d = Duration.fromObject({ minutes: 30 });
const doubled = d.mapUnits(value => value * 2);
Альтернативный способ — преобразование в миллисекунды:
const result = Duration.fromObject({ minutes: 30 })
.as("milliseconds") * 2;
Метод as позволяет получить длительность в конкретной
единице:
const d = Duration.fromObject({
hours: 2,
minutes: 30
});
d.as("minutes"); // 150
d.as("seconds"); // 9000
Это преобразование учитывает все внутренние единицы и возвращает итоговое числовое значение.
Метод shiftTo позволяет перераспределить длительность в
заданные единицы:
const d = Duration.fromObject({
minutes: 150
}).shiftTo("hours", "minutes");
Результат:
2 hours, 30 minutes
Этот метод полезен при форматировании и подготовке данных для отображения.
normalize перераспределяет единицы внутри текущего
набораshiftTo полностью пересчитывает представление в новые
единицыВозвращает объект с текущими единицами:
const d = Duration.fromObject({
hours: 2,
minutes: 30
});
d.toObject();
Результат:
{ hours: 2, minutes: 30 }
Преобразование в ISO 8601:
const d = Duration.fromObject({
hours: 2,
minutes: 30
});
d.toISO();
Результат:
PT2H30M
Luxon поддерживает отрицательные интервалы времени:
const d = Duration.fromObject({ hours: -1, minutes: 30 });
Такие значения возникают при разнице между временными точками или при вычитании длительностей. При преобразованиях важно учитывать знаки всех единиц.
const ms = Duration.fromObject({
minutes: 10
}).as("milliseconds");
const d = Duration.fromMillis(600000);
Хотя Duration не является моментом времени, он часто используется совместно с DateTime:
import { DateTime, Duration } from "luxon";
const start = DateTime.now();
const duration = Duration.fromObject({ hours: 3 });
const end = start.plus(duration);
Метод mapUnits позволяет трансформировать все единицы
сразу:
const d = Duration.fromObject({
hours: 1,
minutes: 30
});
const scaled = d.mapUnits(x => x * 2);
Результат:
2 hours, 60 minutes
Без нормализации значения остаются в исходных единицах.
Объект Duration может быть невалидным при некорректных входных данных:
const d = Duration.fromObject({ hours: NaN });
d.isValid; // false
Ошибочные значения могут возникать при некорректных вычислениях или преобразованиях.
Хотя Interval относится к другому типу Luxon, Duration часто используется для вычисления его длины:
import { Interval } from "luxon";
const interval = Interval.fromDateTimes(
DateTime.now(),
DateTime.now().plus({ hours: 5 })
);
const duration = interval.toDuration();
Luxon поддерживает множество единиц:
При этом важно учитывать, что месяцы и годы не фиксированы по длительности, что влияет на точность вычислений.
Для сравнения используется приведение к общей единице:
const d1 = Duration.fromObject({ minutes: 90 });
const d2 = Duration.fromObject({ hours: 1 });
d1.as("minutes") > d2.as("minutes");
Все операции с Duration возвращают новый объект. Исходная длительность не изменяется:
const d1 = Duration.fromObject({ minutes: 30 });
const d2 = d1.plus({ minutes: 10 });
// d1 остаётся неизменным
Длительность часто выступает базовой единицей для построения временной логики:
const step = Duration.fromObject({ seconds: 5 });
const sequence = Array.from({ length: 5 }, (_, i) =>
step.mapUnits(v => v * i).as("seconds")
);
Такой подход позволяет моделировать равномерные интервалы, таймеры и расписания без привязки к конкретным датам.