408

I want to convert a duration of time, i.e., number of seconds to colon-separated time string (hh:mm:ss)

I found some useful answers here but they all talk about converting to x hours and x minutes format.

So is there a tiny snippet that does this in jQuery or just raw JavaScript?

John Slegers
  • 45,213
  • 22
  • 199
  • 169
medk
  • 9,233
  • 18
  • 57
  • 79
  • 15
    Benchmarks of a few of the suggested answers in this thread. http://jsperf.com/ms-to-hh-mm-ss-time-format – Claudijo Jun 04 '13 at 09:19
  • Possible duplicate of [Convert seconds to HH-MM-SS with JavaScript?](http://stackoverflow.com/questions/1322732/convert-seconds-to-hh-mm-ss-with-javascript) – KyleMit Mar 31 '17 at 17:58

47 Answers47

705
String.prototype.toHHMMSS = function () {
    var sec_num = parseInt(this, 10); // don't forget the second param
    var hours   = Math.floor(sec_num / 3600);
    var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
    var seconds = sec_num - (hours * 3600) - (minutes * 60);

    if (hours   < 10) {hours   = "0"+hours;}
    if (minutes < 10) {minutes = "0"+minutes;}
    if (seconds < 10) {seconds = "0"+seconds;}
    return hours+':'+minutes+':'+seconds;
}

You can use it now like:

alert("5678".toHHMMSS());

Working snippet:

String.prototype.toHHMMSS = function () {
    var sec_num = parseInt(this, 10); // don't forget the second param
    var hours   = Math.floor(sec_num / 3600);
    var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
    var seconds = sec_num - (hours * 3600) - (minutes * 60);

    if (hours   < 10) {hours   = "0"+hours;}
    if (minutes < 10) {minutes = "0"+minutes;}
    if (seconds < 10) {seconds = "0"+seconds;}
    return hours + ':' + minutes + ':' + seconds;
}
    
console.log("5678".toHHMMSS());
powtac
  • 40,542
  • 28
  • 115
  • 170
  • 1
    Thanks for the prototype idea, I like how it is easier to call it. I prototyped the Number so I can call it on them too. I also found [this answer](http://stackoverflow.com/a/5539081/396381) that would remove the hours and minutes if they were not needed. – alunsford3 May 25 '12 at 05:44
  • Just wondering...any particular reason to be passing the seconds in as a string rather than integer? – DA. Jan 19 '14 at 18:09
  • @DA. String will work for Number as well but the other way round not. – powtac Jan 20 '14 at 11:51
  • 26
    use "%" operator >> var minutes = Math.floor((sec_num % 3600) / 60); var seconds = Math.floor(sec_num % 60); – IvanM Mar 31 '14 at 12:50
  • 1
    awesome idea! just curious why string and not Number prototype? since seconds are usually an int and would need to be converted toString. This works for me ((date2 - date1) / 1000).secondsToTimespan() – Sonic Soul Jun 26 '15 at 16:47
  • @sonic-soul see http://stackoverflow.com/questions/6312993/javascript-seconds-to-time-string-with-format-hhmmss/6313008?noredirect=1#comment31982920_6313008 – powtac Jun 26 '15 at 19:11
  • 3
    ah thanks. I don't see it working both ways as a string until you call .toString() on the integer. you can make it work the other way around by parsing int too – Sonic Soul Jun 26 '15 at 21:13
  • 89
    Don't put in on the prototype, just make a utility function. – Michael J. Calkins Oct 07 '15 at 17:42
  • Note: Doesn't work quite right on negative time. (My timer starts at -60 seconds counting towards zero to "start" then continues after that.) – Dustin Graham Jan 09 '17 at 23:21
  • 43
    modify prototype for such thing? 390 upvotes? seriously? – Lukas Liesis May 26 '17 at 14:32
  • 1
    to knock out the hh: if the time is less than an hour, `if(result.length === 8 && result.substring(0,3) === "00:"){ return result.substr(3); } else { return result; }` – Ronnie Royston May 12 '18 at 21:35
  • 1
    I hope this is not how CS is taught at uni these days. The most voted answer is the one that takes a NUMBER of seconds as a string then `parseInt()` it to be able to do the calculations. Seriously. If you deal with days' worth of seconds or negative number, see https://stackoverflow.com/a/55896694/2028733. – Duoc Tran Apr 29 '19 at 03:56
  • 3
    This will fail for certain values and seconds end up showing up as 60. Example 00:14:60. Surprised with the high number of up votes on this solution and nobody seemed to actually test it out thoroughly. – Johann May 07 '19 at 18:17
  • 1
    @AndroidDev it does not. Have a look at this test: https://jsfiddle.net/powtac/1aoLqpr4/ it outputs 00:14:59 and 00:15:00. No way to trigger your result. – powtac May 08 '19 at 07:25
  • @DuocTran Most values, especially when extracted from HTML or for example JSON are strings, because they can be only transmitted as strings. So it's natural to start with reading strings, then in the function parsing the value into int. So the both most common use cases (string and pure int) are covered. No need for the user to differentiate a type value here. – powtac May 08 '19 at 07:28
  • @LukasLiesis Yeah, this does not look good at all. Also, it should not use String but Int input... the other answer is way better. I think the issue is that we cannot take back our vote. Stackoverflow says: "You last voted on this answer 9 mins ago. Your vote is now locked in unless this answer is edited." – Barney Szabolcs May 10 '20 at 21:54
  • 1
    @Barney just edited the answer to run as a helper function. – Lukas Liesis May 11 '20 at 16:51
361

You can manage to do this without any external JS library with the help of JS Date method like following:

var date = new Date(0);
date.setSeconds(45); // specify value for SECONDS here
var timeString = date.toISOString().substring(11, 19);
console.log(timeString)
Vsevolod Goloviznin
  • 12,074
  • 1
  • 49
  • 50
Harish Ambady
  • 12,525
  • 4
  • 29
  • 54
  • 13
    Why is this answer with so low? I get it in 2011 probably IE 7 and 8 was the base which will not support it, but it's end of 2014, so this simple plain, fuss free solution should be way higher. – Emil Borconi Dec 10 '14 at 13:27
  • 2
    From MDN: If a parameter you specify is outside of the expected range, setSeconds() attempts to update the date information in the Date object accordingly. For example, if you use 100 for secondsValue, the minutes stored in the Date object will be incremented by 1, and 40 will be used for seconds. So yeah, looks good! – Andrew Feb 09 '15 at 03:50
  • 71
    I like this answer. It can be even shorter: `new Date(1000 * seconds).toISOString().substr(11, 8)`. – Bohumir Zamecnik Aug 17 '16 at 12:00
  • 11
    Nice answer. You can use `.replace(/^[0:]+/, "")` after `substr` to remove all zeroes and `:` from the start of the string. – Palo Feb 11 '17 at 13:44
  • 6
    Add this in front to handle time over 24h. parseInt(d / 86400) + "d " – Tofandel Oct 17 '19 at 00:17
  • 1
    @Palo that is unnecessary, as `substr` is selecting a segment of the string. You could simply modify the arguments to select the portion of the string you would like to keep. That said, `substr` is being phased out for `substring`, and furthermore `slice` is a very similar method that would probably be more suited to use in your codebase as it is generally more popular in the wild. – Esten Apr 16 '20 at 19:01
  • 2
    Great solution. Adding this obvious bit for those that don't know: If you want only mm:ss, then you change the substr to this: `var timeString = date.toISOString().substr(14, 5);` – Matt Kenefick Apr 28 '20 at 12:31
  • 34
    This breaks if the duration is longer than 23:59:59. – sim642 Sep 26 '20 at 09:05
  • This is great, I turned it into an angular pipe for my project. `@Pipe({ name: 'duration' }) export class DurationPipe implements PipeTransform { transform(value: number): string { const date = new Date(0); date.setSeconds(value); return date.toISOString().substr(11, 8); } }` – Amir Savand Dec 11 '21 at 17:06
  • 3
    Bohumir's comment, but without deprecated substr: `new Date(1000 * seconds).toISOString().substring(11, 19)` – Derkades Aug 20 '22 at 12:02
83

To get the time part in the format hh:MM:ss, you can use this regular expression:

(This was mentioned above in same post by someone, thanks for that.)

    var myDate = new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");
    console.log(myDate)
LWC
  • 1,084
  • 1
  • 10
  • 28
Raj
  • 879
  • 6
  • 2
  • 8
    +1 - Super-simple; thanks! Just used a variant of this to only show the minutes and seconds: `var myDate = new Date().toTimeString().replace(/.*(\d{2}:\d{2})(:\d{2}).*/, "$1");` – Topher Fangio May 17 '13 at 15:11
  • 1
    shouldn't that be "new Date(null, null, null, null, null, timeInSecs).toTimeString().replace(/.*(\d{2}:)(\d{2}:\d{2}).*/, "$2")" ? – obie Aug 27 '13 at 15:36
  • 6
    The use of `replace` is confusing. Why not use `new Date(null, null, null, null, null, timeInSeconds).toTimeString().match(/\d{2}:\d{2}:\d{2}/)[0]` ? – Călin Darie Jan 04 '14 at 19:17
  • 7
    This is fine for showing a given time, but note the question (and other answers here) are about showing a duration, i.e. a given number of seconds independent of the current time. – mahemoff Sep 29 '14 at 19:34
  • how would we have to change regex so it generates hh:MM? – puppeteer701 Aug 04 '15 at 10:04
  • `new Date().toTimeString().replace(/^(\d{2}:\d{2}).*/, "$1")` can be used for hh:MM - note the original regex begins with `/.*`. This is a greedy match and will match minutes and seconds rather than hours and minutes. Using `/^` forces the regex to match at the beginning of the string. – David Clarke Oct 26 '15 at 20:28
  • 1
    Doesn't answer the question. – Eirik Birkeland Feb 10 '16 at 20:04
  • 5
    Simpler version of this: `new Date().toTimeString().split(" ")[0]` – Henrik N Apr 15 '16 at 07:58
  • Very simple. Thank you so much. – Nguyễn Anh Tuấn Jan 09 '17 at 14:57
  • How can I do revert operation? – Umesh Patadiya Apr 15 '19 at 03:38
  • To get elapsed time from this use `new Date(time*1000).toISOString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");` don't use toTimeString or you'll get GMT offset issues – Tofandel Oct 17 '19 at 00:35
  • @HenrikN `Date().split` `[4]` if you want to golf for current HH:MM:SS format. Can be reduced further if aliasing builtins of course. – Pythonista Dec 27 '21 at 08:40
  • Thanks, @Pythonista. That doesn't work as-is for me but `Date().split(" ")[4]` does. – Henrik N Jan 03 '22 at 11:27
  • @HenrikN The comment was messed up. There should be two back ticks after the `split`. Code golf thing. You don't need the parenthesis. Swap the `"` for ticks – Pythonista Jan 03 '22 at 20:35
  • If you use toTimeString in my timezone, you get one hour extra with `console.log(new Date(600000).toTimeString().split(" ")[0])` – mplungjan Dec 20 '22 at 11:16
62

I recommend ordinary javascript, using the Date object. (For a shorter solution, using toTimeString, see the second code snippet.)

var seconds = 9999;
// multiply by 1000 because Date() requires miliseconds
var date = new Date(seconds * 1000);
var hh = date.getUTCHours();
var mm = date.getUTCMinutes();
var ss = date.getSeconds();
// If you were building a timestamp instead of a duration, you would uncomment the following line to get 12-hour (not 24) time
// if (hh > 12) {hh = hh % 12;}
// These lines ensure you have two-digits
if (hh < 10) {hh = "0"+hh;}
if (mm < 10) {mm = "0"+mm;}
if (ss < 10) {ss = "0"+ss;}
// This formats your string to HH:MM:SS
var t = hh+":"+mm+":"+ss;
document.write(t);

(Of course, the Date object created will have an actual date associated with it, but that data is extraneous, so for these purposes, you don't have to worry about it.)


Edit (short solution):

Make use of the toTimeString function and split on the whitespace:

var seconds = 9999; // Some arbitrary value
var date = new Date(seconds * 1000); // multiply by 1000 because Date() requires miliseconds
var timeStr = date.toTimeString().split(' ')[0];

toTimeString gives '16:54:58 GMT-0800 (PST)', and splitting on the first whitespace gives '16:54:58'.

JellicleCat
  • 28,480
  • 24
  • 109
  • 162
  • It seems to make the date in the local time zone, which in my case adds 1 hour to the time. With seconds=0, I get "01:00:00" (Thu Jan 01 1970 01:00:00 GMT+0100 (CET)), which is wrong. – mivk Jun 07 '13 at 15:12
  • 3
    I get a correct result if I use `date.getUTCHours()` and `date.getUTCMinutes()`. – mivk Jun 07 '13 at 16:52
  • I don't understand why you're returning a 12 hour timestamp when he asked for a duration? – Nathan C. Tresch Jan 26 '15 at 21:02
  • @JellicleCat Changed to a +1, and nice name. – Nathan C. Tresch Jan 26 '15 at 23:36
  • 7
    I like this, but it does assume the duration is less than 24h – Rory Jan 28 '18 at 00:20
  • 1
    Add parseInt(d / 86400) + "d " in front to handle cases over 24h – Tofandel Oct 17 '19 at 00:14
  • 3
    Timezones hate this. – Ryan Leach Dec 10 '20 at 14:47
  • yep, the short solution does NOT work with daylight savings. It will add an hour. – Jimbali Aug 05 '22 at 12:53
  • This seems to fix that issue: `const seconds = 9999;` `const date = new Date(Date.UTC(0, 0, 0, 0, 0, seconds));` `const timeStr = date.toTimeString().split(' ')[0];` or even better, use `toLocaleTimeString` and then you don't need to split it: `const seconds = 9999;` `const date = new Date(Date.UTC(0, 0, 0, 0, 0, seconds));` `const timeStr = date.toLocaleTimeString('UTC');` – Jimbali Aug 05 '22 at 13:11
53

Here's my take on it:

function formatTime(seconds) {
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  const s = Math.round(seconds % 60);
  return [
    h,
    m > 9 ? m : (h ? '0' + m : m || '0'),
    s > 9 ? s : '0' + s
  ].filter(Boolean).join(':');
}

Expected results:

const expect = require('expect');
expect(formatTime(0)).toEqual('0:00');
expect(formatTime(1)).toEqual('0:01');
expect(formatTime(599)).toEqual('9:59');
expect(formatTime(600)).toEqual('10:00');
expect(formatTime(3600)).toEqual('1:00:00');
expect(formatTime(360009)).toEqual('100:00:09');
expect(formatTime(0.2)).toEqual('0:00');
Tom Esterez
  • 21,567
  • 8
  • 39
  • 44
  • You could write this as: ```const formatTime = (seconds, h = Math.floor(seconds / 3600), m = Math.floor((seconds % 3600) / 60), s = seconds % 60) => [h, m > 9 ? m : '0' + m, s > 9 ? s : '0' + s].filter(s => s).join(':');``` – Ruben Stolk Jan 08 '18 at 10:06
  • 3
    @RubenStolk I find it a bit confusing to have a function that takes two `second` arguments. I find my version clearer even if it's a bit more verbose. – Tom Esterez Jan 08 '18 at 22:58
  • `seconds: number` type annotations, in es6? – Olian04 Jul 10 '18 at 09:53
  • you've got a superfluous comma at end of: `s > 9 ? s : '0' + s,` – pstanton Feb 03 '20 at 02:47
  • @pstanton trailing comma are legit in JS. I do prefer having them so it's easier to add/remove/move lines: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas – Tom Esterez Feb 03 '20 at 21:46
  • @TomEsterez cause syntax errors in earlier browsers - so subjective at best – pstanton Feb 05 '20 at 06:01
  • 1
    @pstanton trailing comma is supported since IE9: https://caniuse.com/#feat=mdn-javascript_grammar_trailing_commas . I personally choose to ignore those old browsers now. But you're right, I removed it so the answer is more generic. – Tom Esterez Feb 06 '20 at 14:56
  • 2
    Great solution. Maybe just change seconds as `const s = Math.round(seconds % 60);` – Raff Apr 03 '20 at 13:06
  • @Raff, the modulo (%) already returns an integer value so Math.round is not necessary. – Tom Esterez Apr 05 '20 at 17:22
  • 1
    Actually, you're right. The input seconds could have decimals. So I'll change it – Tom Esterez Apr 05 '20 at 17:25
  • 1
    Thanks, this is exactly what I was looking for. Just like Youtube's. – N. Arunoprayoch Aug 05 '21 at 03:10
44

A Google search turned up this result:

function secondsToTime(secs)
{
    secs = Math.round(secs);
    var hours = Math.floor(secs / (60 * 60));

    var divisor_for_minutes = secs % (60 * 60);
    var minutes = Math.floor(divisor_for_minutes / 60);

    var divisor_for_seconds = divisor_for_minutes % 60;
    var seconds = Math.ceil(divisor_for_seconds);

    var obj = {
        "h": hours,
        "m": minutes,
        "s": seconds
    };
    return obj;
}
Ash Burlaczenko
  • 24,778
  • 15
  • 68
  • 99
  • 8
    `secondsToTime(119.9)` => `Object {h: 0, m: 1, s: 60}`. To fix this, add `secs = Math.round(secs);` at the beginning of the method. Of course, we saw this bug during the demo... – Benjamin Crouzier Nov 18 '13 at 11:15
32
function formatTime(seconds) {
    return [
        parseInt(seconds / 60 / 60),
        parseInt(seconds / 60 % 60),
        parseInt(seconds % 60)
    ]
        .join(":")
        .replace(/\b(\d)\b/g, "0$1")
}
meiyang
  • 421
  • 4
  • 4
  • 1
    Further explanation on why this answer would work for the questioner or what may have been wrong in the original question would help raise the quality of this answer. – Josh Burgess Apr 18 '17 at 08:43
  • 2
    Pretty self explainatory and good answer, reduced and simplified the top answer. – AlexioVay Dec 17 '17 at 08:54
  • Precise Answer : ) – Rishav Kumar Feb 05 '19 at 12:35
  • 1
    Short and sweet, very good. Suggest replacing `parseInt` with `Math.floor` esp. if using TypeScript (`parseInt` should have string input) – Aaron B Dec 23 '21 at 21:53
  • 1
    parseInt requires a string, so `seconds` must be a string. In TypeScript, if `seconds` is a `number`, use `Math.floor` instead of `parseInt`. – Lee Goddard Mar 03 '22 at 11:29
  • Suggestion: remove the `parseInt` and instead place `.map(Math.floor)` before `.join(':')`. Also, for better readability, instead of `.replace(/\b(\d)\b/g, "0$1")` after the `.join()`, one could use `.map(n => n.toString().padStart(2, '0'))` before the `.join()`. – Chris Jan 02 '23 at 17:07
32

Variation on a theme. Handles single digit seconds a little differently

seconds2time(0)  ->  "0s" 
seconds2time(59) -> "59s" 
seconds2time(60) -> "1:00" 
seconds2time(1000) -> "16:40" 
seconds2time(4000) -> "1:06:40"

function seconds2time (seconds) {
    var hours   = Math.floor(seconds / 3600);
    var minutes = Math.floor((seconds - (hours * 3600)) / 60);
    var seconds = seconds - (hours * 3600) - (minutes * 60);
    var time = "";

    if (hours != 0) {
      time = hours+":";
    }
    if (minutes != 0 || time !== "") {
      minutes = (minutes < 10 && time !== "") ? "0"+minutes : String(minutes);
      time += minutes+":";
    }
    if (time === "") {
      time = seconds+"s";
    }
    else {
      time += (seconds < 10) ? "0"+seconds : String(seconds);
    }
    return time;
}
jottos
  • 20,098
  • 9
  • 30
  • 27
15

I like the first answer. There some optimisations:

  • source data is a Number. additional calculations is not needed.

  • much excess computing

Result code:

Number.prototype.toHHMMSS = function () {
    var seconds = Math.floor(this),
        hours = Math.floor(seconds / 3600);
    seconds -= hours*3600;
    var minutes = Math.floor(seconds / 60);
    seconds -= minutes*60;

    if (hours   < 10) {hours   = "0"+hours;}
    if (minutes < 10) {minutes = "0"+minutes;}
    if (seconds < 10) {seconds = "0"+seconds;}
    return hours+':'+minutes+':'+seconds;
}
Serge K.
  • 340
  • 4
  • 10
  • 1
    I think this function is a feature used in the fronted and therefor I prototype String and not Number. And Number can always be a string but not the other way round. – powtac Nov 13 '12 at 20:43
  • 4
    I think `Number` is right because `seconds` is, in fact, a number. you should convert from string before using this function, which is the right thing to do! – caesarsol Dec 03 '13 at 09:55
  • 4
    upvoted answer, just like this one, are bad. I bet you don't need ALL numbers to have this method. Do not modify prototype for random utility stuff. – Lukas Liesis May 26 '17 at 14:34
  • or just to prototype and make it a function numToHHMMSS or strTOHHMMSS – yeahdixon Jan 21 '19 at 22:57
  • This solution works while the chosen solution generates seconds of 60 for certain values. – Johann May 07 '19 at 18:26
15

Using the amazing moment.js library:

function humanizeDuration(input, units ) { 
  // units is a string with possible values of y, M, w, d, h, m, s, ms
  var duration = moment().startOf('day').add(units, input),
    format = "";

  if(duration.hour() > 0){ format += "H [hours] "; }

  if(duration.minute() > 0){ format += "m [minutes] "; }

  format += " s [seconds]";

  return duration.format(format);
}

This allows you to specify any duration be it hours, minutes, seconds, mills, and returns a human readable version.

simlmx
  • 999
  • 12
  • 17
Pradeep
  • 418
  • 5
  • 15
14

It's pretty easy,

function toTimeString(seconds) {
  return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0];
}
Strong Bear
  • 411
  • 4
  • 7
11

new Date().toString().split(" ")[4];

result 15:08:03

Artem Kyba
  • 855
  • 1
  • 11
  • 30
  • Nice - thanks! And a small improvement I made for my needs was to convert a duration in milliseconds to HH:MM:SS -- `new Date(new Date().getTime() - startTime).toUTCString().split(" ")[4]` where `startTime` was set previously using `startTime = new Date().getTime();`. (I had to use `toUTCString()` because otherwise the times were an hour out.) – IpsRich Mar 17 '15 at 10:06
11

Easiest way to do it.

new Date(sec * 1000).toISOString().substr(11, 8)
Arjun Kava
  • 5,303
  • 3
  • 20
  • 20
11

Here is an example of using Date.prototype.toLocaleTimeString(). I chose GB as the language, because the US shows a 24 instead of a 00 for the initial hour. Furthermore, I chose Etc/UTC as the time zone, because UTC is aliased to it in the list of tz database time zones.

const formatTime = (seconds) =>
  new Date(seconds * 1000).toLocaleTimeString('en-GB', {
    timeZone:'Etc/UTC',
    hour12: false,
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  });

console.log(formatTime(75)); // 00:01:15
.as-console-wrapper { top: 0; max-height: 100% !important; }

Here is the same example, but with Intl.DateTimeFormat. This variant lets you instantiate a reusable formatter object, which is more performant.

const dateFormatter = new Intl.DateTimeFormat('en-GB', {
  timeZone:'Etc/UTC',
  hour12: false,
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit'
});

const formatTime = (seconds) => dateFormatter.format(new Date(seconds * 1000));

console.log(formatTime(75)); // 00:01:15
.as-console-wrapper { top: 0; max-height: 100% !important; }
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
8
s2t=function (t){
  return parseInt(t/86400)+'d '+(new Date(t%86400*1000)).toUTCString().replace(/.*(\d{2}):(\d{2}):(\d{2}).*/, "$1h $2m $3s");
}

s2t(123456);

result:

1d 10h 17m 36s
Alexis Pigeon
  • 7,423
  • 11
  • 39
  • 44
Andy Wu
  • 81
  • 1
  • 2
7

I loved Powtac's answer, but I wanted to use it in angular.js, so I created a filter using his code.

.filter('HHMMSS', ['$filter', function ($filter) {
    return function (input, decimals) {
        var sec_num = parseInt(input, 10),
            decimal = parseFloat(input) - sec_num,
            hours   = Math.floor(sec_num / 3600),
            minutes = Math.floor((sec_num - (hours * 3600)) / 60),
            seconds = sec_num - (hours * 3600) - (minutes * 60);

        if (hours   < 10) {hours   = "0"+hours;}
        if (minutes < 10) {minutes = "0"+minutes;}
        if (seconds < 10) {seconds = "0"+seconds;}
        var time    = hours+':'+minutes+':'+seconds;
        if (decimals > 0) {
            time += '.' + $filter('number')(decimal, decimals).substr(2);
        }
        return time;
    };
}])

It's functionally identical, except that I added in an optional decimals field to display fractional seconds. Use it like you would any other filter:

{{ elapsedTime | HHMMSS }} displays: 01:23:45

{{ elapsedTime | HHMMSS : 3 }} displays: 01:23:45.678

Mordred
  • 3,734
  • 3
  • 36
  • 55
  • I have two datetime object and and i want to calculate difference of this 2 datetime object and return output like in this format :Hour : Minutes :Seconds with double digit like : 01 : 02 : 45.Can you please tell me or guide me little with your code?? – I Love Stackoverflow Jul 05 '16 at 16:32
7

I liked Webjins answer the most, so i extended it to display days with a d suffix, made display conditional and included a s suffix on plain seconds:

function sec2str(t){
    var d = Math.floor(t/86400),
        h = ('0'+Math.floor(t/3600) % 24).slice(-2),
        m = ('0'+Math.floor(t/60)%60).slice(-2),
        s = ('0' + t % 60).slice(-2);
    return (d>0?d+'d ':'')+(h>0?h+':':'')+(m>0?m+':':'')+(t>60?s:s+'s');
}

returns "3d 16:32:12" or "16:32:12" or "32:12" or "12s"

nïkö
  • 89
  • 2
  • 10
  • This will be incorrect for durations of 24 days or longer – Charlie Martin Dec 07 '15 at 20:54
  • why are you comparing strings greater of 0? – Jimmy Kane Apr 13 '18 at 22:10
  • @JimmyKane because automatic typecasting - i looove it! (plus: code is more easy to read (you've got typecasting for a reason, but let's stop trolling (the both of us)). plus: the function would fail only if t is NaN - so if you want security: do it at the input!) – nïkö Apr 23 '19 at 16:21
  • @nïkö Ok I understand but more strict new JS versions , linters etc can complain about that. Just saying, dong get me wrong. I like your answer – Jimmy Kane Apr 24 '19 at 17:09
4

Here is yet another version, which handles days also:

function FormatSecondsAsDurationString( seconds )
{
    var s = "";

    var days = Math.floor( ( seconds / 3600 ) / 24 );
    if ( days >= 1 )
    {
        s += days.toString() + " day" + ( ( days == 1 ) ? "" : "s" ) + " + ";
        seconds -= days * 24 * 3600;
    }

    var hours = Math.floor( seconds / 3600 );
    s += GetPaddedIntString( hours.toString(), 2 ) + ":";
    seconds -= hours * 3600;

    var minutes = Math.floor( seconds / 60 );
    s += GetPaddedIntString( minutes.toString(), 2 ) + ":";
    seconds -= minutes * 60;

    s += GetPaddedIntString( Math.floor( seconds ).toString(), 2 );

    return s;
}

function GetPaddedIntString( n, numDigits )
{
    var nPadded = n;
    for ( ; nPadded.length < numDigits ; )
    {
        nPadded = "0" + nPadded;
    }

    return nPadded;
}
M Katz
  • 5,098
  • 3
  • 44
  • 66
4
function toHHMMSS(seconds) {
    var h, m, s, result='';
    // HOURs
    h = Math.floor(seconds/3600);
    seconds -= h*3600;
    if(h){
        result = h<10 ? '0'+h+':' : h+':';
    }
    // MINUTEs
    m = Math.floor(seconds/60);
    seconds -= m*60;
    result += m<10 ? '0'+m+':' : m+':';
    // SECONDs
    s=seconds%60;
    result += s<10 ? '0'+s : s;
    return result;
}

Examples

    toHHMMSS(111); 
    "01:51"

    toHHMMSS(4444);
    "01:14:04"

    toHHMMSS(33);
    "00:33"
mashi
  • 532
  • 3
  • 6
  • I'd put a `Math.floor()` on the seconds as well since they might be given in decimals. (Happened with me.) – Winter Sep 11 '16 at 16:02
4

The most general answer to this is

function hms(seconds) {
  return [3600, 60]
    .reduceRight(
      (p, b) => r => [Math.floor(r / b)].concat(p(r % b)),
      r => [r]
    )(seconds)
    .map(a => a.toString().padStart(2, '0'))
    .join(':');
}

Some example outputs:

> hms(0)
< "00:00:00"

> hms(5)
< "00:00:05"

> hms(60)
< "00:01:00"

> hms(3785)
< "01:03:05"

> hms(37850)
< "10:30:50"

> hms(378500)
< "105:08:20"

See explanation at https://stackoverflow.com/a/66504936/1310733

Petr Újezdský
  • 1,233
  • 12
  • 13
4
function secToTime(seconds, separator) {
    return [
        parseInt(seconds / 60 / 60),
        parseInt(seconds / 60 % 60),
        parseInt(seconds % 60)
    ].join(separator ? separator : ':')
    .replace(/\b(\d)\b/g, "0$1").replace(/^00\:/,'')
}

You can use it now like:

alert(secToTime("123"));

Working snippet:

function secToTime(seconds, separator) {
return [
    parseInt(seconds / 60 / 60),
    parseInt(seconds / 60 % 60),
    parseInt(seconds % 60)
].join(separator ? separator : ':')
.replace(/\b(\d)\b/g, "0$1").replace(/^00\:/,'')
}

console.log(secToTime("123"));
RyadPasha
  • 333
  • 3
  • 9
3

I think performance wise this is by far the fastest:

var t = 34236; // your seconds
var time = ('0'+Math.floor(t/3600) % 24).slice(-2)+':'+('0'+Math.floor(t/60)%60).slice(-2)+':'+('0' + t % 60).slice(-2)
//would output: 09:30:36
Rutger van Baren
  • 7,964
  • 2
  • 24
  • 24
2

A regular expression can be used to match the time substring in the string returned from the toString() method of the Date object, which is formatted as follows: "Thu Jul 05 2012 02:45:12 GMT+0100 (GMT Daylight Time)". Note that this solution uses the time since the epoch: midnight of January 1, 1970. This solution can be a one-liner, though splitting it up makes it much easier to understand.

function secondsToTime(seconds) {
    const start = new Date(1970, 1, 1, 0, 0, 0, 0).getTime();
    const end = new Date(1970, 1, 1, 0, 0, parseInt(seconds), 0).getTime();
    const duration = end - start;

    return new Date(duration).toString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");
}
Ninjakannon
  • 3,751
  • 7
  • 53
  • 76
2

Here's how I did it. It seems to work fairly well, and it's extremely compact. (It uses a lot of ternary operators, though)

function formatTime(seconds) {
  var hh = Math.floor(seconds / 3600),
    mm = Math.floor(seconds / 60) % 60,
    ss = Math.floor(seconds) % 60;
  return (hh ? (hh < 10 ? "0" : "") + hh + ":" : "") + ((mm < 10) && hh ? "0" : "") + mm + ":" + (ss < 10 ? "0" : "") + ss
}

...and for formatting strings...

String.prototype.toHHMMSS = function() {
  formatTime(parseInt(this, 10))
};
rookie1024
  • 612
  • 7
  • 18
2

You can use the following function to convert time (in seconds) to HH:MM:SS format :

var convertTime = function (input, separator) {
    var pad = function(input) {return input < 10 ? "0" + input : input;};
    return [
        pad(Math.floor(input / 3600)),
        pad(Math.floor(input % 3600 / 60)),
        pad(Math.floor(input % 60)),
    ].join(typeof separator !== 'undefined' ?  separator : ':' );
}

Without passing a separator, it uses : as the (default) separator :

time = convertTime(13551.9941351); // --> OUTPUT = 03:45:51

If you want to use - as a separator, just pass it as the second parameter:

time = convertTime(1126.5135155, '-'); // --> OUTPUT = 00-18-46

Demo

var convertTime = function (input, separator) {
    var pad = function(input) {return input < 10 ? "0" + input : input;};
    return [
        pad(Math.floor(input / 3600)),
        pad(Math.floor(input % 3600 / 60)),
        pad(Math.floor(input % 60)),
    ].join(typeof separator !== 'undefined' ?  separator : ':' );
}

document.body.innerHTML = '<pre>' + JSON.stringify({
    5.3515555 : convertTime(5.3515555),
    126.2344452 : convertTime(126.2344452, '-'),
    1156.1535548 : convertTime(1156.1535548, '.'),
    9178.1351559 : convertTime(9178.1351559, ':'),
    13555.3515135 : convertTime(13555.3515135, ',')
}, null, '\t') +  '</pre>';

See also this Fiddle.

Community
  • 1
  • 1
John Slegers
  • 45,213
  • 22
  • 199
  • 169
2

There's a new method for strings on the block: padStart

const str = '5';
str.padStart(2, '0'); // 05

Here is a sample use case: YouTube durations in 4 lines of JavaScript

Boris Yakubchik
  • 3,861
  • 3
  • 34
  • 41
2

const secondsToTime = (seconds, locale) => {
    const date = new Date(0);
    date.setHours(0, 0, seconds, 0);
    return date.toLocaleTimeString(locale);
}
console.log(secondsToTime(3610, "en"));

where the locale parameter ("en", "de", etc.) is optional

JukkaP
  • 1,994
  • 1
  • 14
  • 7
2

Here is a fairly simple solution that rounds to the nearest second!

var returnElapsedTime = function(epoch) {
  //We are assuming that the epoch is in seconds
  var hours = epoch / 3600,
      minutes = (hours % 1) * 60,
      seconds = (minutes % 1) * 60;
  return Math.floor(hours) + ":" + Math.floor(minutes) + ":" + Math.round(seconds);
}
Big Sam
  • 1,290
  • 14
  • 7
2

This is one I wrote recently for MM:SS. It's not exact to the question, but it's a different one-liner format.

const time = 60 * 2 + 35; // 2 minutes, 35 seconds
const str = (~~(time / 60) + "").padStart(2, '0') + ":" + (~~((time / 60) % 1 * 60) + "").padStart(2, '0');

str // 02:35

Edit: This was added for variety, but the best solution here is https://stackoverflow.com/a/25279399/639679 below.

Matt Kenefick
  • 1,173
  • 1
  • 13
  • 22
1

This is how i did it

function timeFromSecs(seconds)
{
    return(
    Math.floor(seconds/86400)+'d :'+
    Math.floor(((seconds/86400)%1)*24)+'h : '+
    Math.floor(((seconds/3600)%1)*60)+'m : '+
    Math.round(((seconds/60)%1)*60)+'s');
}

timeFromSecs(22341938) will return '258d 14h 5m 38s'

dt192
  • 1,003
  • 7
  • 12
1

I'm personally prefer the leading unit (days, hours, minutes) without leading zeros. But seconds should always be leaded by minutes (0:13), this presentation is easily considered as 'duration', without further explanation (marking as min, sec(s), etc.), usable in various languages (internationalization).

    // returns  (-)d.h:mm:ss(.f)
    //          (-)h:mm:ss(.f)
    //          (-)m:ss(.f)
    function formatSeconds (value, fracDigits) {
        var isNegative = false;
        if (isNaN(value)) {
            return value;
        } else if (value < 0) {
            isNegative = true;
            value = Math.abs(value);
        }
        var days = Math.floor(value / 86400);
        value %= 86400;
        var hours = Math.floor(value / 3600);
        value %= 3600;
        var minutes = Math.floor(value / 60);
        var seconds = (value % 60).toFixed(fracDigits || 0);
        if (seconds < 10) {
            seconds = '0' + seconds;
        }

        var res = hours ? (hours + ':' + ('0' + minutes).slice(-2) + ':' + seconds) : (minutes + ':' + seconds);
        if (days) {
            res = days + '.' + res;
        }
        return (isNegative ? ('-' + res) : res);
    }

//imitating the server side (.net, C#) duration formatting like:

    public static string Format(this TimeSpan interval)
    {
        string pattern;
        if (interval.Days > 0)          pattern = @"d\.h\:mm\:ss";
        else if (interval.Hours > 0)    pattern = @"h\:mm\:ss";
        else                            pattern = @"m\:ss";
        return string.Format("{0}", interval.ToString(pattern));
    }
1
/**
 * Formats seconds (number) to H:i:s format.
 * 00:12:00
 *
 * When "short" option is set to true, will return:
 * 0:50
 * 2:00
 * 12:00
 * 1:00:24
 * 10:00:00
 */
export default function formatTimeHIS (seconds, { short = false } = {}) {
  const pad = num => num < 10 ? `0${num}` : num

  const H = pad(Math.floor(seconds / 3600))
  const i = pad(Math.floor(seconds % 3600 / 60))
  const s = pad(seconds % 60)

  if (short) {
    let result = ''
    if (H > 0) result += `${+H}:`
    result += `${H > 0 ? i : +i}:${s}`
    return result
  } else {
    return `${H}:${i}:${s}`
  }
}
artnikpro
  • 5,487
  • 4
  • 38
  • 40
1
secToHHMM(number: number) {
    debugger;
    let hours = Math.floor(number / 3600);
    let minutes = Math.floor((number - (hours * 3600)) / 60);
    let seconds = number - (hours * 3600) - (minutes * 60);
    let H, M, S;
    if (hours < 10) H = ("0" + hours);
    if (minutes < 10) M = ("0" + minutes);
    if (seconds < 10) S = ("0" + seconds);
    return (H || hours) + ':' + (M || minutes) + ':' + (S || seconds);
}
Israel
  • 1,165
  • 11
  • 11
0

I'd upvote artem's answer, but I am a new poster. I did expand on his solution, though not what the OP asked for as follows

    t=(new Date()).toString().split(" ");
    timestring = (t[2]+t[1]+' <b>'+t[4]+'</b> '+t[6][1]+t[7][0]+t[8][0]);

To get

04Oct 16:31:28 PDT

This works for me...

But if you are starting with just a time quantity, I use two functions; one to format and pad, and one to calculate:

function sec2hms(timect){

  if(timect=== undefined||timect==0||timect === null){return ''};
  //timect is seconds, NOT milliseconds
  var se=timect % 60; //the remainder after div by 60
  timect = Math.floor(timect/60);
  var mi=timect % 60; //the remainder after div by 60
  timect = Math.floor(timect/60);
  var hr = timect % 24; //the remainder after div by 24
  var dy = Math.floor(timect/24);
  return padify (se, mi, hr, dy);
}

function padify (se, mi, hr, dy){
  hr = hr<10?"0"+hr:hr;
  mi = mi<10?"0"+mi:mi;
  se = se<10?"0"+se:se;
  dy = dy>0?dy+"d ":"";
  return dy+hr+":"+mi+":"+se;
}
0

If you know the number of seconds you have, this will work. It also uses the native Date() object.

function formattime(numberofseconds){    
    var zero = '0', hours, minutes, seconds, time;

    time = new Date(0, 0, 0, 0, 0, numberofseconds, 0);

    hh = time.getHours();
    mm = time.getMinutes();
    ss = time.getSeconds() 

    // Pad zero values to 00
    hh = (zero+hh).slice(-2);
    mm = (zero+mm).slice(-2);
    ss = (zero+ss).slice(-2);

    time = hh + ':' + mm + ':' + ss;
    return time; 
}
webinista
  • 3,750
  • 1
  • 20
  • 21
0

Milliseconds to duration, the simple way:

// To have leading zero digits in strings.
function pad(num, size) {
    var s = num + "";
    while (s.length < size) s = "0" + s;
    return s;
}

// ms to time/duration
msToDuration = function(ms){
    var seconds = ms / 1000;
    var hh = Math.floor(seconds / 3600),
    mm = Math.floor(seconds / 60) % 60,
    ss = Math.floor(seconds) % 60,
    mss = ms % 1000;
    return pad(hh,2)+':'+pad(mm,2)+':'+pad(ss,2)+'.'+pad(mss,3);
}

It converts 327577 to 00:05:27.577.

UPDATE

Another way for different scenario:

toHHMMSS = function (n) {
    var sep = ':',
        n = parseFloat(n),
        sss = parseInt((n % 1)*1000),
        hh = parseInt(n / 3600);
    n %= 3600;
    var mm = parseInt(n / 60),
        ss = parseInt(n % 60);
    return pad(hh,2)+sep+pad(mm,2)+sep+pad(ss,2)+'.'+pad(sss,3);
    function pad(num, size) {
        var str = num + "";
        while (str.length < size) str = "0" + str;
        return str;
    }
}

toHHMMSS(6315.077) // Return 01:45:15.077
Rodrigo Polo
  • 4,314
  • 2
  • 26
  • 32
0

Non-prototype version of toHHMMSS:

    function toHHMMSS(seconds) {
        var sec_num = parseInt(seconds);
        var hours   = Math.floor(sec_num / 3600);
        var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
        var seconds = sec_num - (hours * 3600) - (minutes * 60);        
        if (hours   < 10) {hours   = "0"+hours;}
        if (minutes < 10) {minutes = "0"+minutes;}
        if (seconds < 10) {seconds = "0"+seconds;}
        var time    = hours+':'+minutes+':'+seconds;
        return time;
    }   
joan16v
  • 5,055
  • 4
  • 49
  • 49
0

Here is my vision of solution. You can try my snippet below.

function secToHHMM(sec) {
  var d = new Date();
  d.setHours(0);
  d.setMinutes(0);
  d.setSeconds(0);
  d = new Date(d.getTime() + sec*1000);
  return d.toLocaleString('en-GB').split(' ')[1];
};

alert( 'One hour: ' + secToHHMM(60*60) ); // '01:00:00'
alert( 'One hour five minutes: ' + secToHHMM(60*60 + 5*60) ); // '01:05:00'
alert( 'One hour five minutes 23 seconds: ' + secToHHMM(60*60 + 5*60 + 23) ); // '01:05:23'
Vladimir
  • 342
  • 1
  • 8
0

This version of the accepted answer makes it a bit prettier if you are dealing with video lengths for example:

1:37:40 (1 hour / 37 minutes / 40 seconds)

1:00 (1 minute)

2:20 (2 minutes and 20 seconds)

String.prototype.toHHMMSS = function () {
  var sec_num = parseInt(this, 10); // don't forget the second param
  var hours   = Math.floor(sec_num / 3600);
  var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
  var seconds = sec_num - (hours * 3600) - (minutes * 60);

  var hourSeparator = ':';
  var minuteSeparator = ':';

  if(hours == 0){hours = '';hourSeparator = '';}
  if (minutes < 10 && hours != 0) {minutes = "0"+minutes;}
  if (seconds < 10) {seconds = "0"+seconds;}
  var time = hours+hourSeparator+minutes+minuteSeparator+seconds;
  return time;
}
user1683056
  • 139
  • 8
0
            //secondsToTime();
            var t = wachttijd_sec; // your seconds
            var hour = Math.floor(t/3600);
            if(hour < 10){
                hour = '0'+hour;
            }
            var time = hour+':'+('0'+Math.floor(t/60)%60).slice(-2)+':'+('0' + t % 60).slice(-2);
            //would output: 00:00:00 > +100:00:00

keeps counten down even if more then 24 hours

phpFreak
  • 133
  • 1
  • 1
  • 8
0

You can use Momement.js with moment-duration-format plugin:

var seconds = 3820;
var duration = moment.duration(seconds, 'seconds');
var formatted = duration.format("hh:mm:ss");
console.log(formatted); // 01:03:40
<!-- Moment.js library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>

<!-- moment-duration-format plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/1.3.0/moment-duration-format.min.js"></script>

See also this Fiddle

  • Works like a charm (except format that is not defined) to convert a duration in an object with months, days, hours, minutes and seconds – Pi Home Server Sep 04 '17 at 13:38
0
function secondsToTime(secs)
{
    var hours = Math.floor(secs / (60 * 60));

    var divisor_for_minutes = secs % (60 * 60);
    var minutes = Math.floor(divisor_for_minutes / 60);

    var divisor_for_seconds = divisor_for_minutes % 60;
    var seconds = Math.ceil(divisor_for_seconds);

    if(hours >= 12)
    {
     var m= 'pm' ;
     }
     else
     {
         var m='am'
     }
     if(hours-12 >0)
     {
            var hrs = hours-12;
     }
     else if(hours-12 <0)
     {
            var hrs = hours;
     }
    var obj = {
        "h": hrs,
        "m": minutes,
        "s": seconds,
        "a":m
    };


    return obj;
}
var d = new Date();
var n = d.getHours();
var hms = d.getHours()+':'+d.getMinutes()+':'+d.getSeconds();   // your input string
var a = hms.split(':'); // split it at the colons

// minutes are worth 60 seconds. Hours are worth 60 minutes.
var seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]); 




console.log(seconds);
console.log(secondsToTime(seconds))

https://jsfiddle.net/jithinksoft/9x6z4sdt/

Rakesh
  • 55
  • 2
  • 9
0

Here is an es6 Version of it:

export const parseTime = (time) => { // send time in seconds
// eslint-disable-next-line 
let hours = parseInt(time / 60 / 60), mins = Math.abs(parseInt(time / 60) - (hours * 60)), seconds = Math.round(time % 60);
return isNaN(hours) || isNaN(mins) || isNaN(seconds) ? `00:00:00` : `${hours > 9 ? Math.max(hours, 0) : '0' + Math.max(hours, 0)}:${mins > 9 ? Math.max(mins, 0) : '0' + Math.max(0, mins)}:${seconds > 9 ? Math.max(0, seconds) : '0' + Math.max(0, seconds)}`;}
0

I saw that everybody's posting their takes on the problem despite the fact that few top answers already include all the necessary info to tailor for the specific use case.

And since I want to be hip as well - here's my unnecessary and a bit cumbersome solution, which is:

a) Readable (I hope!)
b) Easily customizable
c) Doesn't print any zeroes

drum roll

function durationToDDHHMMSSMS(durms) {
    if (!durms) return "??";

    var HHMMSSMS = new Date(durms).toISOString().substr(11, 12);
    if (!HHMMSSMS) return "??";

    var HHMMSS = HHMMSSMS.split(".")[0];
    if (!HHMMSS) return "??";

    var MS = parseInt(HHMMSSMS.split(".")[1],10);
    var split = HHMMSS.split(":");
    var SS = parseInt(split[2],10);
    var MM = parseInt(split[1],10);
    var HH = parseInt(split[0],10); 
    var DD = Math.floor(durms/(1000*60*60*24));

    var string = "";
    if (DD) string += ` ${DD}d`;
    if (HH) string += ` ${HH}h`;
    if (MM) string += ` ${MM}m`;
    if (SS) string += ` ${SS}s`;
    if (MS) string += ` ${MS}ms`;

    return string;
},

Note that this code uses ES6 template strings, I'm sure that such a smarty-pants as you are will have no difficulties replacing them with regular strings if required.

Max Yari
  • 3,617
  • 5
  • 32
  • 56
0

Here's a variation of @meiyang's excellent solution that I ended up using:

    function duration(seconds) {
        return [
            format(seconds / 60 / 60),
            format(seconds / 60 % 60),
            format(seconds % 60)
        ].join(':');
    }

    format(n) {
        return (~~n).toString().padStart(2, '0')
    }

PS: It's also worth noting that some of the other solutions above only work for values < 24h

Chris
  • 4,212
  • 5
  • 37
  • 52
-1

Here's a one-liner updated for 2019:

//your date
var someDate = new Date("Wed Jun 26 2019 09:38:02 GMT+0100") 

var result = `${String(someDate.getHours()).padStart(2,"0")}:${String(someDate.getMinutes()).padStart(2,"0")}:${String(someDate.getSeconds()).padStart(2,"0")}`

//result will be "09:38:02"
DataGreed
  • 13,245
  • 8
  • 45
  • 64
-2

I dislike adding properties to standard datatypes in JavaScript, so I would recommend something like this:

/**
 * Format a duration in seconds to a human readable format using the notion
 * "h+:mm:ss", e.g. "4:40:78". Negative durations are preceeded by "-".
 *
 * @param t Duration in seconds
 * @return The formatted duration string
 */
var readableDuration = (function() {

    // Each unit is an object with a suffix s and divisor d
    var units = [
        {s: '', d: 1}, // Seconds
        {s: ':', d: 60}, // Minutes
        {s: ':', d: 60}, // Hours
    ];

    // Closure function
    return function(t) {
        t = parseInt(t); // In order to use modulus
        var trunc, n = Math.abs(t), i, out = []; // out: list of strings to concat
        for (i = 0; i < units.length; i++) {
            n = Math.floor(n / units[i].d); // Total number of this unit
            // Truncate e.g. 26h to 2h using modulus with next unit divisor
            if (i+1 < units.length) // Tweak substr with two digits
                trunc = ('00'+ n % units[i+1].d).substr(-2, 2); // …if not final unit
            else
                trunc = n;
            out.unshift(''+ trunc + units[i].s); // Output
        }
        (t < 0) ? out.unshift('-') : null; // Handle negative durations
        return out.join('');
    };
})();

Usage:

var str = readableDuration(3808); // "1:03:28"

I also created a more generally usable version. The main difference is that it accepts milliseconds (which is kind of the standard time unit in JS) and the output format uses spaces instead.

Betamos
  • 26,448
  • 9
  • 23
  • 28