Как отформатировать продолжительность как 2:30:45?
Отображение продолжительности времени в формате цифровых часов с двоеточиями
Введение
Видеоплееры, секундомеры и таймеры обратного отсчета отображают длительность в привычном формате. Вы видите "2:30:45" и сразу понимаете, что это означает 2 часа, 30 минут и 45 секунд. Этот формат цифровых часов использует двоеточия для разделения единиц времени без меток или пробелов.
Создание этого формата вручную требует дополнения чисел нулями и обработки различных длительностей. Видео длительностью 5 минут и 30 секунд отображается как "5:30", а видео на 2 часа — как "2:00:00". Логика становится сложной из-за крайних случаев.
function formatDuration(seconds) {
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
if (h > 0) {
return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
}
return `${m}:${String(s).padStart(2, '0')}`;
}
API Intl.DurationFormat автоматически обрабатывает это с помощью опции стиля digital. Он создает правильный формат для любой длительности.
const duration = { hours: 2, minutes: 30, seconds: 45 };
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "2:30:45"
Используйте цифровой стиль для отображения таймеров
Стиль digital форматирует длительности как цифровые часы. Установите опцию style в значение "digital" при создании форматтера.
const formatter = new Intl.DurationFormat('en', { style: 'digital' });
Передайте объект длительности с единицами времени, которые вы хотите отобразить. Форматтер добавляет двоеточия между единицами и дополняет значения нулями, где это необходимо.
const duration = { hours: 1, minutes: 5, seconds: 30 };
formatter.format(duration);
// "1:05:30"
Обратите внимание, как минуты отображаются как "05" вместо "5". Форматтер автоматически дополняет минуты до двух цифр, когда присутствуют часы. Это поддерживает выравнивание в списках и таблицах.
Для длительностей без часов исключите это свойство из объекта длительности.
const shortDuration = { minutes: 5, seconds: 30 };
formatter.format(shortDuration);
// "5:30"
Минуты больше не требуют дополнения, когда они являются наибольшей единицей. Формат остается компактным, но при этом понятным.
Как цифровой формат обрабатывает разные длины продолжительности
Цифровой формат настраивает вывод в зависимости от того, какие единицы вы включаете в объект продолжительности. Это соответствует тому, как видеоплееры адаптируют свой дисплей к длине видео.
Короткая продолжительность показывает только минуты и секунды.
const formatter = new Intl.DurationFormat('en', { style: 'digital' });
const short = { minutes: 3, seconds: 42 };
formatter.format(short);
// "3:42"
Более длительная продолжительность включает часы.
const long = { hours: 2, minutes: 15, seconds: 8 };
formatter.format(long);
// "2:15:08"
Когда появляются часы, все меньшие единицы дополняются до двух цифр. Когда часы отсутствуют, минуты отображаются без дополнения, но секунды всё равно дополняются.
Это правило дополнения создаёт согласованное выравнивание без лишнего пространства. Список коротких видео показывает "5:30", "12:45", "8:02" с выровненными двоеточиями. Список длинных видео показывает "1:05:30", "2:12:45", "3:08:02" с единообразным форматированием.
Включайте только те единицы, которые нужны вашему интерфейсу. Таймер обратного отсчёта, который никогда не превышает одного часа, может полностью исключить часы.
const countdown = { minutes: 42, seconds: 15 };
formatter.format(countdown);
// "42:15"
Управление дополнением нулями и параметрами отображения
Цифровой формат использует правила дополнения по умолчанию, но вы можете переопределить их, указав параметры для отдельных единиц времени.
Управляйте отображением каждой единицы, задавая параметры для конкретных единиц. Значение numeric показывает число без дополнения. Значение 2-digit принудительно добавляет два знака.
const duration = { hours: 1, minutes: 5, seconds: 3 };
new Intl.DurationFormat('en', {
style: 'digital',
hours: 'numeric',
minutes: '2-digit',
seconds: '2-digit'
}).format(duration);
// "1:05:03"
Это поведение по умолчанию. Вам нужно указывать эти параметры только в том случае, если вы хотите другое форматирование.
Принудительно отображайте часы всегда с двумя цифрами.
new Intl.DurationFormat('en', {
style: 'digital',
hours: '2-digit',
minutes: '2-digit',
seconds: '2-digit'
}).format(duration);
// "01:05:03"
Этот формат хорошо подходит для синхронизированных дисплеев, где согласованная ширина предотвращает сдвиги макета.
Удалите дополнение из секунд для более компактного отображения.
const shortDuration = { minutes: 5, seconds: 3 };
new Intl.DurationFormat('en', {
style: 'digital',
seconds: 'numeric'
}).format(shortDuration);
// "5:3"
Этот формат менее распространён, так как пользователи ожидают дополнения секунд в цифровых дисплеях.
Добавление долей секунды в цифровой формат
Некоторым приложениям требуется отображать миллисекунды или микросекунды. Цифровой формат поддерживает доли секунды с помощью опции fractionalDigits.
Укажите, сколько знаков после запятой отображать после секунд.
const duration = {
minutes: 5,
seconds: 30,
milliseconds: 123
};
new Intl.DurationFormat('en', {
style: 'digital',
fractionalDigits: 3
}).format(duration);
// "5:30.123"
Форматировщик добавляет десятичную точку после секунд и отображает указанное количество дробных знаков.
Секундомеры обычно показывают сотые доли секунды.
const lap = {
minutes: 1,
seconds: 23,
milliseconds: 450
};
new Intl.DurationFormat('en', {
style: 'digital',
fractionalDigits: 2
}).format(lap);
// "1:23.45"
Форматировщик округляет до указанной точности. Значение 450 миллисекунд становится 45 сотыми.
Для точности до микросекунд включите микросекунды в объект продолжительности и установите большее количество дробных знаков.
const precise = {
seconds: 42,
milliseconds: 123,
microseconds: 456
};
new Intl.DurationFormat('en', {
style: 'digital',
fractionalDigits: 6
}).format(precise);
// "42.123456"
Когда использовать цифровой формат вместо других стилей
Выбирайте цифровой формат, если ваш интерфейс напоминает таймер, секундомер или медиаплеер. Пользователи ожидают этот формат в таких контекстах.
Используйте цифровой формат для элементов управления видеоплеера.
function formatVideoTime(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
const duration = hours > 0
? { hours, minutes, seconds: secs }
: { minutes, seconds: secs };
return new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
}
formatVideoTime(6345); // "1:45:45"
formatVideoTime(125); // "2:05"
Используйте цифровой формат для таймеров обратного отсчета и секундомеров.
function formatStopwatch(milliseconds) {
const minutes = Math.floor(milliseconds / 60000);
const seconds = Math.floor((milliseconds % 60000) / 1000);
const ms = milliseconds % 1000;
return new Intl.DurationFormat('en', {
style: 'digital',
fractionalDigits: 2
}).format({ minutes, seconds, milliseconds: ms });
}
formatStopwatch(125450); // "2:05.45"
Используйте другие стили, если отображаете продолжительность в тексте или если метки улучшают ясность. Сайты бронирования авиабилетов показывают "8 ч 15 мин" вместо "8:15:00", потому что контекст не является таймером.
// Подходит для текста и описаний
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 ч, 46 мин и 40 сек"
// Подходит для отображения таймеров
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "1:46:40"
Создание цифрового формата вручную для старых браузеров
Intl.DurationFormat API стал доступен в марте 2025 года. Для старых браузеров создавайте цифровой формат вручную.
Ручной подход требует вычисления единиц времени из общего количества секунд и дополнения значений нулями.
function formatDigitalDuration(totalSeconds) {
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = Math.floor(totalSeconds % 60);
if (hours > 0) {
const paddedMinutes = String(minutes).padStart(2, '0');
const paddedSeconds = String(seconds).padStart(2, '0');
return `${hours}:${paddedMinutes}:${paddedSeconds}`;
} else {
const paddedSeconds = String(seconds).padStart(2, '0');
return `${minutes}:${paddedSeconds}`;
}
}
formatDigitalDuration(6345); // "1:45:45"
formatDigitalDuration(125); // "2:05"
Функция делит общее количество секунд на 3600, чтобы получить часы. Остаток, делённый на 60, даёт минуты. Оставшийся остаток — это секунды.
Метод padStart() добавляет ведущие нули, если значение меньше 10. Это гарантирует, что "5" становится "05" для единообразного форматирования.
Для длительностей, хранящихся как объекты длительности, а не общее количество секунд, извлекайте значения напрямую.
function formatDurationObject(duration) {
const h = duration.hours || 0;
const m = duration.minutes || 0;
const s = duration.seconds || 0;
if (h > 0) {
return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
}
return `${m}:${String(s).padStart(2, '0')}`;
}
formatDurationObject({ hours: 1, minutes: 5, seconds: 30 }); // "1:05:30"
formatDurationObject({ minutes: 5, seconds: 30 }); // "5:30"
Добавьте доли секунд, включая миллисекунды, и отформатируйте с десятичной точностью.
function formatWithMilliseconds(duration) {
const m = duration.minutes || 0;
const s = duration.seconds || 0;
const ms = duration.milliseconds || 0;
const paddedSeconds = String(s).padStart(2, '0');
const fractional = String(ms).padStart(3, '0').slice(0, 2);
return `${m}:${paddedSeconds}.${fractional}`;
}
formatWithMilliseconds({ minutes: 1, seconds: 23, milliseconds: 450 });
// "1:23.45"
Проверьте поддержку API перед его использованием.
function formatDuration(duration) {
if (typeof Intl.DurationFormat !== 'undefined') {
return new Intl.DurationFormat('ru', { style: 'digital' }).format(duration);
} else {
return formatDurationObject(duration);
}
}
Этот подход обеспечивает единообразный вывод во всех браузерах, используя нативный API, если он доступен.
Общие шаблоны для видеоплееров и таймеров
Видеоплееры должны форматировать как текущее время, так и общую продолжительность. Создайте переиспользуемый форматтер для обработки обоих значений.
const videoFormatter = new Intl.DurationFormat('ru', { style: 'digital' });
function formatVideoPosition(currentSeconds, totalSeconds) {
const current = secondsToDuration(currentSeconds);
const total = secondsToDuration(totalSeconds);
return `${videoFormatter.format(current)} / ${videoFormatter.format(total)}`;
}
function secondsToDuration(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
return hours > 0
? { hours, minutes, seconds: secs }
: { minutes, seconds: secs };
}
formatVideoPosition(125, 6345); // "2:05 / 1:45:45"
Для таймеров обратного отсчета, которые обновляются каждый кадр, создайте форматтер один раз и переиспользуйте его.
const timerFormatter = new Intl.DurationFormat('ru', {
style: 'digital',
fractionalDigits: 2
});
function updateTimer(remainingMs) {
const duration = {
minutes: Math.floor(remainingMs / 60000),
seconds: Math.floor((remainingMs % 60000) / 1000),
milliseconds: remainingMs % 1000
};
document.getElementById('timer').textContent = timerFormatter.format(duration);
}
Для секундомеров, которые показывают время кругов, форматируйте прошедшее время с дробными секундами.
const lapFormatter = new Intl.DurationFormat('ru', {
style: 'digital',
fractionalDigits: 3
});
function formatLapTime(startMs, endMs) {
const elapsedMs = endMs - startMs;
return lapFormatter.format({
minutes: Math.floor(elapsedMs / 60000),
seconds: Math.floor((elapsedMs % 60000) / 1000),
milliseconds: elapsedMs % 1000
});
}
const lap1Start = performance.now();
// ... время проходит ...
const lap1End = performance.now();
formatLapTime(lap1Start, lap1End); // "1:23.456"
Эти шаблоны обрабатывают наиболее распространенные сценарии форматирования продолжительности, сохраняя при этом чистый и переиспользуемый код.