Как отформатировать длительность как 2:30:45?
Показ времени в формате цифровых часов с двоеточиями
Введение
Видеоплееры, секундомеры и таймеры обратного отсчёта показывают длительность в привычном формате. Вы видите «2:30:45» и сразу понимаете, что это 2 часа, 30 минут и 45 секунд. Такой цифровой формат использует двоеточия для разделения единиц времени без подписей и пробелов.
Чтобы собрать такой формат вручную, нужно дополнять числа нулями и учитывать разную длину длительности. Видео на 5 минут 30 секунд отображается как «5:30», а двухчасовое видео — как «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», потому что это не таймер.
// Good for prose and descriptions
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min and 40 sec"
// Good for timer displays
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "1:46:40"
Как вручную собрать цифровой формат для старых браузеров
API Intl.DurationFormat появилось в марте 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» для единообразного формата.
Если длительность хранится как объект duration, а не как общее количество секунд, извлекайте значения напрямую.
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('en', { style: 'digital' }).format(duration);
} else {
return formatDurationObject(duration);
}
}
Такой подход обеспечивает одинаковый результат во всех браузерах, используя нативный API, если он доступен.
Типовые шаблоны для видеоплееров и таймеров
Видеоплееры должны форматировать как текущее время, так и общую длительность. Создайте переиспользуемый форматтер для обоих значений.
const videoFormatter = new Intl.DurationFormat('en', { 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('en', {
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('en', {
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();
// ... time passes ...
const lap1End = performance.now();
formatLapTime(lap1Start, lap1End); // "1:23.456"
Эти шаблоны охватывают самые частые сценарии форматирования длительности и позволяют поддерживать чистый, переиспользуемый код.