Работа с длительностями в Moment.js основана на объекте
Duration, который представляет промежуток времени в
миллисекундах, но предоставляет множество методов для преобразования и
отображения этого интервала в разных единицах. Округление длительностей
— один из ключевых аспектов, поскольку практически любые прикладные
задачи (таймеры, отчёты, аналитика, UI-индикаторы времени) требуют не
точных миллисекунд, а сглаженных, читаемых значений.
Любая длительность в Moment.js создаётся через
moment.duration():
const d = moment.duration(125000); // 125000 мс
Внутренне значение хранится точно, без округления. Проблема возникает при преобразовании:
Moment.js не применяет автоматическое округление, оставляя это разработчику.
Методы извлечения времени возвращают дробные значения:
d.asSeconds(); // 125
d.asMinutes(); // 2.0833333333
Особенность: округления нет, всегда возвращается “сырой” float.
Для целых значений используются:
d.seconds(); // 5
d.minutes(); // 2
Но важно понимать:
minutes() — это “остаток минут”, а не общее
количествоasMinutes() — полное значение с дробьюСамый прямой способ — использовать стандартные функции Jav * aScript:
Math.floor(d.asMinutes()); // 2
Используется в:
Math.ceil(d.asMinutes()); // 3
Используется в:
Math.round(d.asMinutes()); // 2
Используется:
Math.floor(d.asSeconds());
Math.round(d.asSeconds());
Практика:
Math.floor(d.asMinutes());
Типичный кейс:
Math.floor(d.asHours());
Используется:
При последовательных преобразованиях легко получить дрейф:
const hours = Math.floor(d.asHours());
const minutes = Math.floor(d.asMinutes());
Ошибка: minutes содержит общее количество минут, а не
остаток после часов.
Правильный подход:
const hours = Math.floor(d.asHours());
const minutes = Math.floor(d.asMinutes()) % 60;
Для точного представления длительности:
const d = moment.duration(3675, 'seconds');
const hours = Math.floor(d.asHours());
const minutes = Math.floor(d.asMinutes()) % 60;
const seconds = Math.floor(d.asSeconds()) % 60;
Это позволяет избежать накопления дробей и корректно разложить время.
Moment.js позволяет получить структуру:
d.hours();
d.minutes();
d.seconds();
Но важно:
Поэтому часто комбинируется с asX() и
Math.
function formatDuration(d) {
const minutes = Math.floor(d.asMinutes());
if (minutes < 60) {
return `${minutes} мин`;
}
const hours = Math.floor(d.asHours());
const restMinutes = minutes % 60;
return `${hours} ч ${restMinutes} мин`;
}
function smartRound(duration) {
const minutes = duration.asMinutes();
if (minutes < 1) return "меньше минуты";
if (minutes < 60) return Math.round(minutes) + " мин";
return Math.round(duration.asHours()) + " ч";
}
Moment.js поддерживает отрицательные durations:
const d = moment.duration(-125000);
Поведение Math:
Math.floor(-2.1) = -3Math.round(-2.1) = -2Это часто приводит к логическим ошибкам.
Корректный подход:
const minutes = Math.abs(d.asMinutes());
или явная нормализация:
const sign = d.asMilliseconds() < 0 ? -1 : 1;
const minutes = Math.floor(Math.abs(d.asMinutes())) * sign;
d.humanize();
Этот метод:
Пример:
Это автоматическое округление, не настраиваемое напрямую.
При работе с миллисекундами:
const d = moment.duration(1999);
Math.floor(d.asSeconds()); // 1
Math.round(d.asSeconds()); // 2
Разница критична для:
d.minutes(); // остаток
d.asMinutes(); // общее значение
Math.round(Math.round(d.asMinutes()));
Math.floor(d.asSeconds());
без учёта дробных значений при расчётах UI может давать скачки.
Иногда требуется нестандартная логика:
function roundToFive(mins) {
return Math.round(mins / 5) * 5;
}
function roundToQuarter(mins) {
return Math.round(mins / 15) * 15;
}
const rounded = roundToQuarter(d.asMinutes());
При работе с длительностями в Moment.js важно разделять три уровня:
Именно последний слой определяет поведение системы в реальных интерфейсах и бизнес-логике.