Converting milliseconds to minutes and seconds with Javascript
Asked Answered
O

16

122

Soundcloud's API gives the duration of it's tracks as milliseconds. JSON looks like this:

"duration": 298999

I've tried many functions I found on here to no avail. I'm just looking for something to convert that number to something like looks like this:

4:59

Here's one that got close, but doesn't work. It doesn't stop the seconds at 60. It goes all the way to 99 which makes no sense. Try entering "187810" as a value of ms, for example.

var ms = 298999,
min = Math.floor((ms/1000/60) << 0),
sec = Math.floor((ms/1000) % 60);

console.log(min + ':' + sec);

Thanks for your help!

If you could add in support for hours, too, I would be grateful.

Oenone answered 22/1, 2014 at 21:26 Comment(8)
What do you mean, "it goes all the way to 99"? Your script is working for me, properly outputting 4:58. Please provide an input that leads to the unexpected output.Ruction
187810 is an example of it not working. It's goes all the way to 99. There are not 99 seconds in a minute.Oenone
That yields 3:7 (maybe should be 3:07) for me. Where do you see 99 in there?Ruction
I don't know, I copied this code, Bergi.Oenone
From where? It would be nice to reference the origins :-)Ruction
Here, added Math.floor to it since I copied. #5588965Oenone
Thanks. As you can see in the comments, << 0 just did the same as your Math.floorRuction
Great, suppose either works. Math.floor seemed to be what most people were using.Oenone
T
262
function millisToMinutesAndSeconds(millis) {
  var minutes = Math.floor(millis / 60000);
  var seconds = ((millis % 60000) / 1000).toFixed(0);
  return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
}

millisToMinutesAndSeconds(298999); // "4:59"
millisToMinutesAndSeconds(60999);  // "1:01"

As User HelpingHand pointed in the comments the return statement should be:

return (
  seconds == 60 ?
  (minutes+1) + ":00" :
  minutes + ":" + (seconds < 10 ? "0" : "") + seconds
);
Thunderstone answered 22/1, 2014 at 21:43 Comment(7)
Let it be known that this solution sometimes results in sixty seconds in the second place when nearing conversion to the next minute (ex. 1:60). I stop this from happening by adding an inline if statement in the last line: return (seconds == 60 ? (minutes+1) + ":00" : minutes + ":" + (seconds < 10 ? "0" : "") + seconds); You can see it in action hereSaucedo
That's a good point by HelpingHand - you can reproduce the issue by running millisToMinutesAndSeconds(299900)Bracy
@Thunderstone Shouldn't ((millis % 60000) / 1000).toFixed(0) be Math.floor((millis % 60000) / 1000) so seconds is a number instead of a string when it is being compared to another number.Schenk
return should be return minutes + ":" + seconds.ToString("00"), where seconds should be (Math.Round(millis % 60000 / 1000, 0, MidpointRounding.ToEven);Homophonic
Proposal of renaming for this function: formatToISODuration ... don't bother with the millisecond in the name, the parameter does the job. And always write user-PoV names, no inner technical details. Plus "And" in a function name is always a bad idea.Baca
Please don't do this. Use native JS date/time functions. No matter what language you're programming in, if you ever find yourself doing manual temporal conversions/manipulations, stop. It's almost always been solved already. Please see my answer.Sapajou
var seconds = Math.floor((millis % 60000) / 1000);Gauleiter
S
32

I'm not really sure why these answers are all so complex. The Date class gives you what you need:

const date = new Date(298999);

alert(`${date.getMinutes()}:${date.getSeconds()}`);

Although the above meets op's requirements, adding this updated version in response to @ianstarz comment regarding timezone independence:

const d = new Date(Date.UTC(0,0,0,0,0,0,298999)),
  // Pull out parts of interest
  parts = [
    d.getUTCHours(),
    d.getUTCMinutes(),
    d.getUTCSeconds()
  ],
  // Zero-pad
  formatted = parts.map(s => String(s).padStart(2,'0')).join(':');

document.write(formatted);
Sapajou answered 10/9, 2021 at 3:8 Comment(6)
Looks like OP is indeed only asking for seconds and minutes. This solution would not work for hours and days however. date.getHours() // => 16 (in my timezone)Directorial
@Directorial updated my solution to make it more universally applicableSapajou
Should probably be higher up the list, However if the seconds are < 10, then it would output something like 4:5Anelace
@Anelace updated with a more complete exampleSapajou
@Sapajou you might want to do it for your first example too, otherwise the simplicity is misleadingAnelace
This should be the accepted answer as it is simpler, less error prone than other solutions and uses the language's built-in resourcesEaglestone
S
22

With hours, 0-padding minutes and seconds:

var ms = 298999;
var d = new Date(1000*Math.round(ms/1000)); // round to nearest second
function pad(i) { return ('0'+i).slice(-2); }
var str = d.getUTCHours() + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds());
console.log(str); // 0:04:59

Sherd answered 22/1, 2014 at 21:33 Comment(4)
In some use cases it might be better to drop the second (2nd) row (rounding to the nearest second). For example, if we want to know the full seconds left, this would return "4:58".Sheared
presumably if you're over 60 minutes you'd want to add getUTCHours?Mango
@Sapajou if you're suggesting pad is reinventing the wheel, note the answer is from 2014 yet your use of padStart is part of EMCAScript 2017.Sherd
@Sherd my bad. I deleted my previous comment. I do suggest using native JS classes/functions however when possible.Sapajou
S
6

Here's my contribution if looking for

h:mm:ss

instead like I was:

function msConversion(millis) {
  let sec = Math.floor(millis / 1000);
  let hrs = Math.floor(sec / 3600);
  sec -= hrs * 3600;
  let min = Math.floor(sec / 60);
  sec -= min * 60;

  sec = '' + sec;
  sec = ('00' + sec).substring(sec.length);

  if (hrs > 0) {
    min = '' + min;
    min = ('00' + min).substring(min.length);
    return hrs + ":" + min + ":" + sec;
  }
  else {
    return min + ":" + sec;
  }
}
Saucedo answered 2/6, 2019 at 1:45 Comment(0)
T
3

There is probably a better way to do this, but it gets the job done:

var ms = 298999;
var min = ms / 1000 / 60;
var r = min % 1;
var sec = Math.floor(r * 60);
if (sec < 10) {
    sec = '0'+sec;
}
min = Math.floor(min);
console.log(min+':'+sec);

Not sure why you have the << operator in your minutes line, I don't think it's needed just floor the minutes before you display.

Getting the remainder of the minutes with % gives you the percentage of seconds elapsed in that minute, so multiplying it by 60 gives you the amount of seconds and flooring it makes it more fit for display although you could also get sub-second precision if you want.

If seconds are less than 10 you want to display them with a leading zero.

Terbium answered 22/1, 2014 at 21:43 Comment(0)
B
3

Event though ,oment.js does not provide such functionality, if you come here and you are already using moment.js, try this:

function formatDuration(ms) {
  var duration = moment.duration(ms);
  return Math.floor(duration.asHours()) + moment.utc(duration.asMilliseconds()).format(":mm:ss");
}

You will get something like x:xx:xx.

In the case you may want to skip the hour, when the duration is only < 60minutes.

function formatDuration(ms) {
  var duration = moment.duration(ms);
  if (duration.asHours() > 1) {
    return Math.floor(duration.asHours()) + moment.utc(duration.asMilliseconds()).format(":mm:ss");
  } else {
    return moment.utc(duration.asMilliseconds()).format("mm:ss");
  }
}

This workaround in moment was introduced in this Issue.

Bradlybradman answered 18/2, 2016 at 21:49 Comment(0)
N
3

Best is this!

function msToTime(duration) {
var milliseconds = parseInt((duration%1000))
    , seconds = parseInt((duration/1000)%60)
    , minutes = parseInt((duration/(1000*60))%60)
    , hours = parseInt((duration/(1000*60*60))%24);

hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;

return hours + ":" + minutes + ":" + seconds + "." + milliseconds;
}

It will return 00:04:21.223 You can format this string then as you wish.

Nuncio answered 21/10, 2019 at 20:7 Comment(4)
No need to reinvent the wheel. Look at the Date class and the methods it offers you. The "best" is always to use native solutions.Sapajou
@Sapajou I'm not sure how you would do pure formatting like this with date since you would have to deal with timezones. Can you provide and example of what you mean?Directorial
@Directorial I added an answer.Sapajou
this solution it terrible. why do you divide milliseconds by 1000 to get milliseconds?Egwan
U
0
function msToHMS( ms ) {
  // 1- Convert to seconds:
  var seconds = ms / 1000;

  // 2- Extract hours:
  var hours = parseInt( seconds / 3600 ); // 3,600 seconds in 1 hour
  seconds = seconds % 3600; // seconds remaining after extracting hours

  // 3- Extract minutes:
  var minutes = parseInt( seconds / 60 ); // 60 seconds in 1 minute

  // 4- Keep only seconds not extracted to minutes:
  seconds = seconds % 60;

  //alert( hours+":"+minutes+":"+seconds);
  hours = (hours < 10) ? "0" + hours : hours;
  minutes = (minutes < 10) ? "0" + minutes : minutes;
  seconds = (seconds < 10) ? "0" + seconds : seconds;
  var hms = hours+":"+minutes+":"+seconds;
  return hms;
}
Usage answered 17/7, 2020 at 15:3 Comment(0)
L
0

If you do not need support for hours, there's a clever little way of doing this with momentjs and dayjs.

dayjs(ms).format("mm:ss")

or

moment(ms).format("mm:ss")

A millisecond timestamp passed to MomentJS and DayJS will be interpreted as the number of milliseconds since the Unix Epoch, therefore any time duration not affected by timezone (ie any number of milliseconds less than one hour) will be interpreted correctly.

Languishing answered 16/3, 2022 at 0:23 Comment(0)
P
0
// ✅ You can use a Quick one-liner hack
 const ms = 54000000;
console.log(new `enter code here`Date(ms).toISOString().slice(11, 19)); // 👉️ 15:00:00

// ------------------------------------------------

// ✅ Or create a reusable function
function padTo2Digits(num) {
  return num.toString().padStart(2, '0');
}

function convertMsToTime(milliseconds) {
  let seconds = Math.floor(milliseconds / 1000);
  let minutes = Math.floor(seconds / 60);
  let hours = Math.floor(minutes / 60);

  seconds = seconds % 60;
  minutes = minutes % 60;

  // 👇️ If you don't want to roll hours over, e.g. 24 to 00
  // 👇️ comment (or remove) the line below
  // commenting next line gets you `24:00:00` instead of `00:00:00`
  // or `36:15:31` instead of `12:15:31`, etc.
  hours = hours % 24;

  return `${padTo2Digits(hours)}:${padTo2Digits(minutes)}:${padTo2Digits(
    seconds,
  )}`;
}

console.log(convertMsToTime(54000000)); // 👉️ 15:00:00 (15 hours)
console.log(convertMsToTime(86400000)); // 👉️ 00:00:00 (24 hours)
console.log(convertMsToTime(36900000)); // 👉️ 10:15:00 (10 hours, 15 minutes)
console.log(convertMsToTime(15305000)); // 👉️ 04:15:05 (4 hours, 15 minutes, 5 seconds)
Phineas answered 5/7, 2023 at 13:38 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Marxist
I
0
const ms = 298999;
const mmss = new Date(ms).toLocaleTimeString().substring(3);
console.log(mmss); // 04:58
Insurgency answered 8/3 at 0:11 Comment(1)
There's a lot of existing answers already, but this one look reasonably different from all of them.Lafleur
A
-1

Just works:

const minute = Math.floor(( milliseconds % (1000 * 60 * 60)) / (1000 * 60));

const second = Math.floor((ms % (1000 * 60)) / 1000);
Alishiaalisia answered 30/3, 2020 at 20:41 Comment(0)
M
-1
const Minutes = ((123456/60000).toFixed(2)).replace('.',':');

//Result = 2:06

We divide the number in milliseconds (123456) by 60000 to give us the same number in minutes, which here would be 2.0576.

toFixed(2) - Rounds the number to nearest two decimal places, which in this example gives an answer of 2.06.

You then use replace to swap the period for a colon.

Magpie answered 14/10, 2020 at 11:45 Comment(0)
A
-1

My solution: Input: 11381 (in ms) Output: 00 : 00 : 11.381

 timeformatter(time) {
    console.log(time);

    let miliSec = String(time%1000);
    time = (time - miliSec)/1000;
    let seconds = String(time%60);
    time = (time - seconds)/60;
    let minutes = String(time%60);
    time = (time-minutes)/60;
    let hours = String(time)

    while(miliSec.length != 3 && miliSec.length<3 && miliSec.length >=0) {
        miliSec = '0'+miliSec;
    }
    while(seconds.length != 2 && seconds.length<3 && seconds.length >=0) {
        seconds = '0'+seconds;
    }
    while(minutes.length != 2 && minutes.length<3 && minutes.length >=0) {
        minutes = '0'+minutes;
    }
    while(hours.length != 2 && hours.length<3 && hours.length >=0) {
        hours = '0'+hours;
    }
    return `${hours}  : ${minutes} : ${seconds}.${miliSec}`
}
Anishaaniso answered 16/12, 2020 at 11:28 Comment(1)
it's unnecessary to covert numbers to stringsJeanninejeans
K
-2

this code will do a better job if you want to show hours, and centiseconds or miliseconds after seconds like 1:02:32.21 and if used in a cell phone the timer will show correct timing even after screen lock.

<div id="timer" style="font-family:monospace;">00:00<small>.00</small></div>

<script>
var d = new Date();
var n = d.getTime();
var startTime = n;

var tm=0;
function updateTimer(){
  d = new Date();
  n = d.getTime();
  var currentTime = n;  
  tm = (currentTime-startTime);
  
  //tm +=1; 
  // si el timer cuenta en centesimas de segundo
  //tm = tm*10;
  
  var hours = Math.floor(tm / 1000 / 60 / 60);
  var minutes = Math.floor(tm / 60000) % 60;
  var seconds =  ((tm / 1000) % 60);
  // saca los decimales ej 2 d{0,2}
  var seconds = seconds.toString().match(/^-?\d+(?:\.\d{0,-1})?/)[0];
  var miliseconds = ("00" + tm).slice(-3);
  var centiseconds;

  
  // si el timer cuenta en centesimas de segundo
  //tm = tm/10;


  centiseconds = miliseconds/10;
  centiseconds = (centiseconds).toString().match(/^-?\d+(?:\.\d{0,-1})?/)[0];

  minutes = (minutes < 10 ? '0' : '') + minutes;
  seconds = (seconds < 10 ? '0' : '') + seconds;
  centiseconds = (centiseconds < 10 ? '0' : '') + centiseconds;
  hours = hours + (hours > 0 ? ':' : '');
  if (hours==0){
    hours='';
  }

  document.getElementById("timer").innerHTML = hours + minutes + ':' + seconds + '<small>.' + centiseconds + '</small>';
}

var timerInterval = setInterval(updateTimer, 10);
// clearInterval(timerInterval);
</script>
Kery answered 23/9, 2017 at 7:54 Comment(2)
Your answer is not entirely bad. It's mostly off-topic. The question was about formatting, not about displaying and also not about updating time. There are also some problems in the code. The code is not really re-usable because of lack of separation (mixed formatting with updating). You are also calculating seconds twice and using inefficient ways to do the calculations (RegExp)...Noelnoelani
hi Nux thanks, I understand, just came across this issue when needed to display time in a web app served by an arduino, the js code runs at client side only once, it doesnt mean to scale. The time calculation in the top anwer doesnt actually works. secconds/100 dont match with seconds at runtime, and if the browser looses focus the timer looses the count. If you try my code it covers all needs about calculation, formating, and diplaying, of course if you can make it re-usable and performant, please send me the snippet. Thanks!Kery
O
-2
const millisToMinutesAndSeconds(millis)=> {
      const minutes=Math.floor(millis/60/1000) % 60;
      const seconds=Math.floor(millis/1000) % 60;
      return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
}
Otherness answered 9/2, 2023 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.