Moment.js предоставляет слой абстракции над временем, в котором
длительности становятся самостоятельными объектами, а не просто
числовыми разницами в миллисекундах. Основная модель работы с
длительностями строится вокруг moment.duration, позволяющей
выполнять арифметику времени в разных единицах — от миллисекунд до лет —
с автоматической нормализацией и конвертацией.
Длительность в Moment.js — это не просто число, а структура, хранящая компоненты времени:
Такое разделение важно, потому что разные единицы времени имеют неоднородную природу: дни и месяцы не эквивалентны в фиксированном числовом выражении.
const d = moment.duration(2, 'hours');
Внутренне библиотека хранит это значение в нормализованной форме, но операции могут выполняться как на уровне компонентов, так и через общее представление в миллисекундах.
Сложение длительностей позволяет формировать составные интервалы времени.
const d1 = moment.duration(2, 'hours');
const d2 = moment.duration(30, 'minutes');
const result = moment.duration(d1 + d2);
Однако прямое сложение объектов через оператор +
приводит к неявному преобразованию в число (миллисекунды), поэтому
корректнее использовать явную работу с миллисекундами:
const result = moment.duration(
d1.asMilliseconds() + d2.asMilliseconds()
);
Такой подход устраняет неоднозначность и сохраняет точность вычислений.
Вычитание реализуется аналогично сложению через числовое представление:
const d1 = moment.duration(5, 'hours');
const d2 = moment.duration(90, 'minutes');
const diff = moment.duration(
d1.asMilliseconds() - d2.asMilliseconds()
);
Результатом может быть отрицательная длительность, что важно учитывать при дальнейших операциях.
После выполнения операций длительность может содержать «переполненные» единицы измерения. Например, 90 минут не обязаны автоматически превращаться в 1 час 30 минут в разложенном виде при ручной работе с компонентами.
Moment.js поддерживает автоматическую нормализацию при конвертации:
const d = moment.duration(90, 'minutes');
d.hours(); // 1
d.minutes(); // 30
Нормализация происходит при чтении отдельных компонентов, но не всегда при внутреннем хранении результата арифметики, если она выполнена через миллисекунды.
Основная математическая модель операций с длительностями сводится к единой шкале — миллисекундам:
const total = d1.asMilliseconds() + d2.asMilliseconds();
const result = moment.duration(total);
Это позволяет:
Прямой операции умножения в API нет, поэтому используется преобразование:
const d = moment.duration(1, 'hour');
const doubled = moment.duration(d.asMilliseconds() * 2);
Такой подход сохраняет линейную модель времени, где длительность рассматривается как скалярная величина в миллисекундах.
Деление используется для вычисления среднего интервала или разбиения периода:
const d = moment.duration(2, 'hours');
const half = moment.duration(d.asMilliseconds() / 2);
При делении важно учитывать округление, поскольку итоговое значение снова переводится в целое число миллисекунд при создании новой длительности.
Длительности часто используются совместно с моментами времени:
const start = moment('2026-01-01 10:00');
const duration = moment.duration(90, 'minutes');
const end = start.clone().add(duration);
Метод add интерпретирует длительность как смещение по
временной оси.
const end = moment('2026-01-01 12:00');
const duration = moment.duration(30, 'minutes');
const start = end.clone().subtract(duration);
Операция эквивалентна смещению назад по временной шкале.
Moment.js позволяет работать с частями длительности напрямую:
const d = moment.duration({
hours: 1,
minutes: 45
});
d.add(15, 'minutes');
Однако такая форма требует осторожности: при сложных комбинациях возможны эффекты накопления значений без немедленной полной нормализации.
Каждая длительность может быть преобразована в любую единицу:
const d = moment.duration(3600, 'seconds');
d.asMinutes(); // 60
d.asHours(); // 1
При арифметике рекомендуется использовать единое представление:
asMilliseconds()При вычитании может возникнуть отрицательное значение:
const d1 = moment.duration(1, 'hour');
const d2 = moment.duration(2, 'hours');
const result = moment.duration(d1.asMilliseconds() - d2.asMilliseconds());
Такой результат сохраняет знак и может использоваться для определения направления разницы во времени.
result.asMilliseconds(); // отрицательное число
При извлечении компонентов важно учитывать, что отрицательные длительности могут давать неожиданные значения при разложении по единицам.
Сравнение выполняется через миллисекунды:
const d1 = moment.duration(2, 'hours');
const d2 = moment.duration(90, 'minutes');
if (d1.asMilliseconds() > d2.asMilliseconds()) {
// d1 больше
}
Это единственный устойчивый способ сравнения, поскольку компонентная модель не является линейной во всех единицах.
При последовательных вычислениях длительности часто используются аккумуляторы:
const durations = [
moment.duration(30, 'minutes'),
moment.duration(45, 'minutes'),
moment.duration(1, 'hour')
];
let total = moment.duration(0);
for (const d of durations) {
total = moment.duration(total.asMilliseconds() + d.asMilliseconds());
}
Такой подход гарантирует корректную агрегацию независимо от единиц.
При операциях деления возможны дробные миллисекунды:
const d = moment.duration(1, 'second');
const result = moment.duration(d.asMilliseconds() / 3);
Фактическое значение будет округлено до ближайшего целого миллисекундного значения, что важно учитывать при высокой точности расчётов.
При создании длительности из смешанных единиц арифметика становится неявной:
const d = moment.duration({
days: 1,
hours: 5,
minutes: 30
});
При преобразовании в миллисекунды происходит сведение всех компонентов к общей шкале:
d.asMilliseconds();
Однако обратное разложение может отличаться в зависимости от внутренних правил нормализации.
Арифметика длительностей имеет фундаментальные ограничения:
Эти ограничения определяют необходимость использования миллисекунд как базовой единицы при любых точных вычислениях.
Многократные преобразования длительности между единицами и обратно приводят к накоплению погрешностей:
let d = moment.duration(1, 'hour');
for (let i = 0; i < 10; i++) {
d = moment.duration(d.asMilliseconds() + 1000);
}
Каждая итерация сохраняет точность в пределах миллисекундной сетки, но при сложных сценариях это может приводить к расхождениям в разложении на компоненты.
Длительности часто применяются в цепочках операций:
const base = moment.duration(1, 'hour');
const result = moment.duration(
base.asMilliseconds()
+ moment.duration(30, 'minutes').asMilliseconds()
- moment.duration(15, 'minutes').asMilliseconds()
);
Такая форма делает вычисления прозрачными и детерминированными, независимо от исходных единиц.