Skip to main content

How to Convert Milliseconds to Hours, Minutes, and Seconds in JavaScript

Converting a duration from milliseconds into a human-readable HH:MM:SS format is a common requirement for displaying timers, video durations, or countdowns. This conversion involves a series of mathematical operations to extract the different time components from the total number of milliseconds.

This guide will teach you how to create a single, robust function to convert milliseconds into a formatted time string. We will cover the core mathematical logic using division and the modulo operator, and explain how to handle values that exceed 24 hours.

The Core Concepts: Division and the Modulo Operator

The key to this conversion is a two-step process for each unit of time (hours, minutes, seconds).

  1. Division: You divide the total number of milliseconds by the appropriate conversion factor to get the total number of hours, minutes, or seconds. Math.floor() is used to get only the whole number part.
  2. Modulo (%): The modulo operator gives you the remainder of a division. We use it to "subtract" the larger units of time so we can calculate the next, smaller unit. For example, once we've calculated the total hours, we use the modulo operator to get the "leftover" minutes.

The Solution: A Reusable msToTime Function

This function encapsulates all the necessary logic and provides a clean, zero-padded HH:MM:SS string as output.

For example, you have a duration in milliseconds (e.g., from Date.now() - startTime) and need to display it as a formatted time. How to convert this duration into HH:MM:SS?

// Problem: How to convert this duration into "10:15:30"?
const durationInMs = 36930000;

The solution:

function msToTime(duration) {
const milliseconds = Math.floor((duration % 1000) / 100);
let seconds = Math.floor((duration / 1000) % 60);
let minutes = Math.floor((duration / (1000 * 60)) % 60);
let hours = Math.floor((duration / (1000 * 60 * 60)) % 24);

// Use `padStart` to add a leading zero if the value is less than 10.
hours = hours.toString().padStart(2, '0');
minutes = minutes.toString().padStart(2, '0');
seconds = seconds.toString().padStart(2, '0');

return `${hours}:${minutes}:${seconds}`;
}

// Example Usage:
console.log(msToTime(36930000)); // Output: "10:15:30"
console.log(msToTime(54000000)); // Output: "15:00:00"
console.log(msToTime(86400000)); // Output: "00:00:00" (rolls over after 24 hours)

How the Logic Works

Let's break down the function with an example input of 36930000 ms.

  1. Calculate Total Hours:

    • 36930000 / (1000 * 60 * 60) = 10.258... hours.
    • Math.floor(...) gives us 10.
    • The % 24 ensures the hours "wrap around" after 23 (e.g., 25 hours becomes 1).
  2. Calculate Total Minutes:

    • 36930000 / (1000 * 60) = 615.5 minutes.
    • Math.floor(...) gives us 615.
    • 615 % 60 gives us the remainder of 15, which is the minutes part of our final time.
  3. Calculate Total Seconds:

    • 36930000 / 1000 = 36930 seconds.
    • Math.floor(...) gives us 36930.
    • 36930 % 60 gives us the remainder of 30, which is the seconds part.
  4. Padding: The padStart(2, '0') method is a clean, modern way to ensure each component is two digits long, adding a leading 0 if necessary (e.g., 5 becomes '05').

Handling Durations Longer Than 24 Hours

The example function above uses % 24 on the hours, which means it will wrap back to 00 after 23 hours. This is useful for displaying time of day, but for a simple duration, you might want to show the total number of hours, even if it's greater than 24.

Solution: to show total hours, simply remove the % 24 from the hours calculation.

function msToTotalHoursTime(duration) {
let seconds = Math.floor((duration / 1000) % 60);
let minutes = Math.floor((duration / (1000 * 60)) % 60);
// The only change is removing `% 24` from the hours calculation.
let hours = Math.floor(duration / (1000 * 60 * 60));

hours = hours.toString().padStart(2, '0');
minutes = minutes.toString().padStart(2, '0');
seconds = seconds.toString().padStart(2, '0');

return `${hours}:${minutes}:${seconds}`;
}

// 36 hours in milliseconds
const longDuration = 129600000;

console.log(msToTotalHoursTime(longDuration)); // Output: "36:00:00"

Practical Example: A Simple Stopwatch Display

This script simulates a stopwatch and uses our msToTime function to update the display.

const startTime = Date.now();

// This function will be called every second to update the display
function updateTimer() {
const elapsedTime = Date.now() - startTime;

const formattedTime = msToTime(elapsedTime);

// In a real app, you would update a DOM element here.
console.clear(); // Clear the console for a clean display
console.log(`Elapsed Time: ${formattedTime}`);
}

// Helper function from above
function msToTime(duration) {
const milliseconds = Math.floor((duration % 1000) / 100);
let seconds = Math.floor((duration / 1000) % 60);
let minutes = Math.floor((duration / (1000 * 60)) % 60);
let hours = Math.floor((duration / (1000 * 60 * 60)) % 24);

// Use `padStart` to add a leading zero if the value is less than 10.
hours = hours.toString().padStart(2, '0');
minutes = minutes.toString().padStart(2, '0');
seconds = seconds.toString().padStart(2, '0');

return `${hours}:${minutes}:${seconds}`;
}

// Start the timer to update every second
setInterval(updateTimer, 1000);

Conclusion

Converting milliseconds to a formatted time string is a common task that can be solved with straightforward arithmetic.

  • The core of the logic is using division and the modulo operator (%) to extract the hours, minutes, and seconds from the total milliseconds.
  • The String.prototype.padStart() method is the best modern tool for adding leading zeros to ensure consistent formatting.
  • By encapsulating this logic in a reusable function like msToTime(), you can create clean and maintainable code for any time-display needs.