В библиотеке Moment.js работа с временными интервалами реализована через объект duration, который предназначен для представления и преобразования длительностей независимо от конкретной даты. В отличие от объекта moment, который описывает точку во времени, duration оперирует промежутками: часами, минутами, секундами, днями и более крупными единицами.
Длительность не привязана к календарю, однако внутри реализации существуют важные нюансы, связанные с переменной длиной месяцев и лет. Это делает конвертацию между единицами не всегда строго линейной операцией.
Основной способ создания длительности:
const d = moment.duration(2, 'hours');
Допустимые единицы включают:
Также возможно создание через объект:
const d = moment.duration({
hours: 3,
minutes: 45,
seconds: 30
});
Или через общее количество миллисекунд:
const d = moment.duration(7200000);
Объект duration предоставляет набор методов для преобразования в различные единицы времени.
d.asMilliseconds();
Возвращает полное количество миллисекунд, включая все составляющие единицы.
d.asSeconds();
d.asMinutes();
d.asHours();
Каждый из методов возвращает значение в соответствующей единице с учётом дробной части.
Пример:
const d = moment.duration(90, 'minutes');
d.asHours(); // 1.5
d.asMinutes(); // 90
d.asSeconds(); // 5400
d.asDays();
d.asWeeks();
Важно учитывать, что неделя всегда считается как 7 дней, однако дни могут включать дробные значения:
const d = moment.duration(36, 'hours');
d.asDays(); // 1.5
Месяцы и годы в duration являются неоднородными единицами. Один месяц может содержать 28, 29, 30 или 31 день, а год — 365 или 366 дней.
const d = moment.duration(1, 'month');
d.asDays(); // зависит от контекста и внутренней нормализации
По этой причине конвертация в дни или часы может давать приближённые значения. Для точных расчётов рекомендуется избегать прямых преобразований месяцев и лет в меньшие единицы.
Помимо преобразования в одну единицу, duration позволяет извлекать отдельные компоненты:
d.hours();
d.minutes();
d.seconds();
Эти методы возвращают остаточные значения после нормализации.
Пример:
const d = moment.duration(2, 'hours')
.add(30, 'minutes');
d.hours(); // 2
d.minutes(); // 30
При работе с несколькими единицами библиотека автоматически нормализует значения:
const d = moment.duration({
minutes: 90,
seconds: 120
});
Результат:
После нормализации:
d.hours(); // 1
d.minutes(); // 32
d.seconds(); // 0
Метод as() позволяет получать значение в произвольной
единице:
d.as('hours');
d.as('minutes');
d.as('seconds');
Это универсальный интерфейс, аналогичный специализированным методам, но с динамическим выбором единицы.
Конвертация длительности часто требует округления значений:
Math.floor(d.asHours());
Math.ceil(d.asHours());
Math.round(d.asHours());
Moment.js не навязывает стратегию округления, предоставляя её на уровень приложения.
Длительность может изменяться до преобразования:
const d = moment.duration(1, 'hour');
d.add(30, 'minutes');
d.subtract(10, 'minutes');
d.asMinutes(); // 80
Методы:
Работают с нормализацией и сохраняют внутреннюю структуру duration.
Поддерживается формат ISO 8601:
d.toISOString();
Пример результата:
PT1H30M
Этот формат используется в API и системах обмена данными.
Метод humanize преобразует длительность в текстовое описание:
d.humanize();
Примеры:
При этом результат зависит от локали и округления.
При преобразовании длительности между крупными и мелкими единицами возможна потеря точности:
const d = moment.duration(1, 'year');
d.asDays();
Такое преобразование зависит от внутреннего представления года и может варьироваться.
Для сравнения удобно использовать миллисекунды:
const a = moment.duration(2, 'hours');
const b = moment.duration(90, 'minutes');
a.asMilliseconds() > b.asMilliseconds();
Этот подход исключает неоднозначность месяцев и лет.
При создании длительности с несколькими компонентами:
const d = moment.duration({
days: 1,
hours: 5,
minutes: 20,
seconds: 10
});
Конвертация в различные единицы:
d.asHours(); // 29.335...
d.asMinutes(); // 1760.166...
d.asSeconds(); // 105610
Duration поддерживает отрицательные интервалы:
const d = moment.duration(-2, 'hours');
Конвертация сохраняет знак:
d.asMinutes(); // -120
При извлечении компонентов знак может проявляться отдельно:
d.hours(); // 2 (при этом duration отрицательная)
Ключевые ограничения:
Эти особенности требуют выбора подходящего метода в зависимости от задачи: точные вычисления или отображение пользователю.
Duration может быть разобрана и восстановлена:
const d = moment.duration(2, 'hours');
const obj = {
hours: d.hours(),
minutes: d.minutes()
};
const restored = moment.duration(obj);
Такой подход используется при сериализации и хранении состояния времени.