90

I need a code snippet for converting amount of time given by number of seconds into some human readable form. The function should receive a number and output a string like this:

34 seconds 
12 minutes 
4 hours 
5 days 
4 months
1 year

No formatting required, hard-coded format will go.

Dan
  • 55,715
  • 40
  • 116
  • 154
  • 3
    possible duplicate of [How to convert milliseconds into human readable form?](http://stackoverflow.com/questions/175554/how-to-convert-milliseconds-into-human-readable-form) – nfechner Nov 21 '11 at 12:26
  • yes and no, I was thinking there is a good JavaScript solution for this... – Dan Nov 21 '11 at 12:35
  • Seconds is a human readable form. – nnnnnn Nov 21 '11 at 12:43
  • 3
    Well, "213123 seconds" is not so readable. You can propose a better title – Dan Nov 21 '11 at 12:47

26 Answers26

88
 function secondsToString(seconds)
{
var numyears = Math.floor(seconds / 31536000);
var numdays = Math.floor((seconds % 31536000) / 86400); 
var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;
return numyears + " years " +  numdays + " days " + numhours + " hours " + numminutes + " minutes " + numseconds + " seconds";

}
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • 1
    Thanks! If you add checking for plural(year/years) it would be perfect! – Dan Nov 21 '11 at 12:34
  • Thanks for your help, Royi. See my answer below which answers my question completely – Dan Nov 21 '11 at 13:51
  • 5
    and the magic numbers: `secondsInAYear = 31536000; secondsInADay = 86400; secondsInAnHour = 3600; secondsInAMinute = 60;` – Jake Berger Sep 10 '13 at 07:03
  • 4
    Note: This doesn't take into account leap years, and only provides the values as a "span of time". – James Wilkins Nov 15 '13 at 02:48
  • 1
    `(((seconds % 31536000) % 86400) % 3600) % 60 === seconds % 60` so you can save some bits that will die in your cpu `var numyears = Math.floor(seconds / 31536000); var numdays = Math.floor((seconds % 31536000) / 86400); var numhours = Math.floor((seconds % 86400) / 3600); var numminutes = Math.floor((seconds % 3600) / 60); var numseconds = seconds % 60;` – mr_tron Mar 22 '17 at 10:22
77

With help of Royi we've got code that outputs time interval in a human readable form:

function millisecondsToStr (milliseconds) {
    // TIP: to find current time in milliseconds, use:
    // var  current_time_milliseconds = new Date().getTime();

    function numberEnding (number) {
        return (number > 1) ? 's' : '';
    }

    var temp = Math.floor(milliseconds / 1000);
    var years = Math.floor(temp / 31536000);
    if (years) {
        return years + ' year' + numberEnding(years);
    }
    //TODO: Months! Maybe weeks? 
    var days = Math.floor((temp %= 31536000) / 86400);
    if (days) {
        return days + ' day' + numberEnding(days);
    }
    var hours = Math.floor((temp %= 86400) / 3600);
    if (hours) {
        return hours + ' hour' + numberEnding(hours);
    }
    var minutes = Math.floor((temp %= 3600) / 60);
    if (minutes) {
        return minutes + ' minute' + numberEnding(minutes);
    }
    var seconds = temp % 60;
    if (seconds) {
        return seconds + ' second' + numberEnding(seconds);
    }
    return 'less than a second'; //'just now' //or other string you like;
}
Dan
  • 55,715
  • 40
  • 116
  • 154
  • 5
    This is wrong. For the time like '3 day 0 hour 50 minutes 36 seconds', it only gets '3 day', because it returns when hour is coincidentailly "0". – user2909913 Jul 25 '21 at 12:51
  • TO make it more relevant if the value is not 0 then need to concat with the varible. for i.e. let returnText = ''; if (days && days !== 0) { returntext += days + ' day' + numberEnding(days); } – Rahul Dhamecha Apr 25 '22 at 11:02
  • @user2909913 It in facts return when day is not 0 and not when hours is 0, so it basically floors the result to the nearest unit (which in some case might be desirable because it's much shorter in all cases) – Tofandel Jun 08 '22 at 12:02
65

If you are interested in an existing javascript library that does the job very well, you may want to check moment.js.

More specifically, the relevant moment.js piece for your question is durations.

Here are some examples of how you can take advantage of it to achieve your task:

var duration = moment.duration(31536000);

// Using the built-in humanize function:
console.log(duration.humanize());   // Output: "9 hours"
console.log(duration.humanize(true));   // Output: "in 9 hours"

moment.js has built-in support for 50+ human languages, so if you use the humanize() method you get multi-language support for free.

If you want to display the exact time information, you can take advantage of the moment-precise-range plug-in for moment.js that was created exactly for this purpose:

console.log(moment.preciseDiff(0, 39240754000);
// Output: 1 year 2 months 30 days 5 hours 12 minutes 34 seconds

One thing to note is that currently moment.js does not support weeks / days (in week) for duration object.

Hope this helps!

urish
  • 8,943
  • 8
  • 54
  • 75
  • 6
    It's quite imprecise. `moment.duration(40, 'seconds')` yields `'a few seconds'`. `moment.duration(45, 'seconds')` yields `'a minute'`. [see this Feature request](https://github.com/moment/moment/issues/348) – testworks Jan 27 '17 at 05:36
  • moment.js is [deprecated](https://momentjs.com/docs/#/-project-status/) since 2020. A useful currently maintained library for this would be [humanize-duration](https://github.com/EvanHahn/HumanizeDuration.js). – codeflorist Mar 17 '23 at 08:54
40

Took a swing based on @Royi's response:

/**
 * Translates seconds into human readable format of seconds, minutes, hours, days, and years
 * 
 * @param  {number} seconds The number of seconds to be processed
 * @return {string}         The phrase describing the amount of time
 */
function forHumans ( seconds ) {
    var levels = [
        [Math.floor(seconds / 31536000), 'years'],
        [Math.floor((seconds % 31536000) / 86400), 'days'],
        [Math.floor(((seconds % 31536000) % 86400) / 3600), 'hours'],
        [Math.floor((((seconds % 31536000) % 86400) % 3600) / 60), 'minutes'],
        [(((seconds % 31536000) % 86400) % 3600) % 60, 'seconds'],
    ];
    var returntext = '';

    for (var i = 0, max = levels.length; i < max; i++) {
        if ( levels[i][0] === 0 ) continue;
        returntext += ' ' + levels[i][0] + ' ' + (levels[i][0] === 1 ? levels[i][1].substr(0, levels[i][1].length-1): levels[i][1]);
    };
    return returntext.trim();
}

Nice thing about mine is that there is no repetitive ifs, and won't give you 0 years 0 days 30 minutes 1 second for example.

For example:

forHumans(60) outputs 1 minute

forHumans(3600) outputs 1 hour

and forHumans(13559879) outputs 156 days 22 hours 37 minutes 59 seconds

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
xyhhx
  • 6,384
  • 6
  • 41
  • 64
16

Try following:

seconds = ~~(milliseconds / 1000);
minutes = ~~(seconds / 60);
hours = ~~(minutes / 60);
days = ~~(hours / 24);
weeks = ~~(days / 7);
year = ~~(days / 365);

Note:

  • A usual year has 365 days. A leap year has 366 days, so you need additional check if this is an issue for you.
  • The similar problem with daylight saving. Some days have 23 and some 25 hours when time's changed.

Conclusion: this is a rude but small and simple snippet :)

Dan
  • 55,715
  • 40
  • 116
  • 154
Reporter
  • 3,897
  • 5
  • 33
  • 47
  • Rewritten your code a bit according to bemchmark tests showing `parseInt` is too slow – Dan Apr 16 '13 at 08:44
  • This does not work. For instance, if milliseconds is 300000 (5 minutes) then this gives milliseconds=300000, seconds=300, minutes=5, which is not the output the OP requested. https://jsfiddle.net/yp6fcacs/ – Nathan Apr 22 '18 at 22:07
15

Way more simple and readable.

milliseconds = 12345678;
mydate=new Date(milliseconds);
humandate=mydate.getUTCHours()+" hours, "+mydate.getUTCMinutes()+" minutes and "+mydate.getUTCSeconds()+" second(s)";

Which gives:

"3 hours, 25 minutes and 45 second(s)"

Zibri
  • 9,096
  • 3
  • 52
  • 44
  • 1
    This is a very good answer, and if I needed to output a **date 'Anno Domini'**, this would be the accepted answer. Instead, I needed to transform a **time interval**, into string like `1 month ago`. Totally my fault, my question was not clear. Thanks to you it was noticed, and the question was updated. – Dan Apr 19 '14 at 19:31
  • Very interesting pitfall for those who have to deal with dates and time intervals. If we counted the epoch since 0, not since 1970, this problem would not exist. – Dan Apr 19 '14 at 19:33
  • Your code works good until the interval is less than one year, and when **daylight saving is not taken into account**. – Dan Apr 19 '14 at 19:36
  • @Dan I did that on purpose. to account for daylight saving remove UTC from all the last line. – Zibri Dec 01 '19 at 09:43
14
millisToTime = function(ms){

    x = ms / 1000;
    seconds = Math.round(x % 60);
    x /= 60;
    minutes = Math.round(x % 60);
    x /= 60;
    hours = Math.round(x % 24);
    x /= 24;
    days = Math.round(x);

    return {"Days" : days, "Hours" : hours, "Minutes" : minutes, "Seconds" : seconds};
}

This will take milliseconds as an int, and give you an JSON object containing all the info you could need

RiggsFolly
  • 93,638
  • 21
  • 103
  • 149
galv
  • 141
  • 2
  • 4
  • 2
    Thanks for the function. In my case, I have to change Math.round(x) to Math.floor(x) to get the numbers that I need. – Hong Feb 07 '15 at 23:26
10

To Convert time in millisecond to human readable format.

 function timeConversion(millisec) {

        var seconds = (millisec / 1000).toFixed(1);

        var minutes = (millisec / (1000 * 60)).toFixed(1);

        var hours = (millisec / (1000 * 60 * 60)).toFixed(1);

        var days = (millisec / (1000 * 60 * 60 * 24)).toFixed(1);

        if (seconds < 60) {
            return seconds + " Sec";
        } else if (minutes < 60) {
            return minutes + " Min";
        } else if (hours < 24) {
            return hours + " Hrs";
        } else {
            return days + " Days"
        }
    }

"Out Put Sample"

Nofi
  • 2,107
  • 1
  • 15
  • 23
5

Thanks to @Dan / @ Royi for the logic. However the implementation doesn't build time string like XX days, XX mins. I adjusted their code a bit:

function millisecondsToStr( milliseconds ) {
    let temp = milliseconds / 1000;
    const years = Math.floor( temp / 31536000 ),
          days = Math.floor( ( temp %= 31536000 ) / 86400 ),
          hours = Math.floor( ( temp %= 86400 ) / 3600 ),
          minutes = Math.floor( ( temp %= 3600 ) / 60 ),
          seconds = temp % 60;

    if ( days || hours || seconds || minutes ) {
      return ( years ? years + "y " : "" ) +
      ( days ? days + "d " : "" ) +
      ( hours ? hours + "h " : ""  ) +
      ( minutes ? minutes + "m " : "" ) +
      Number.parseFloat( seconds ).toFixed( 2 ) + "s";
    }

    return "< 1s";
}

When one runs it

console.log("=", millisecondsToStr( 1540545689739 - 1540545684368 ));
console.log("=", millisecondsToStr( 351338536000 ));

The results look like:

= 5.37s
= 11y 51d 10h 2m 16.00s
Dmitry Sheiko
  • 2,130
  • 1
  • 25
  • 28
5

Adding to the myriad of methods, here's a cheap and short way to retrieve a human readable time with only a single time unit.

const timeScalars = [1000, 60, 60, 24, 7, 52];
const timeUnits = ['ms', 'secs', 'mins', 'hrs', 'days', 'weeks', 'years'];

const getHumanReadableTime = (ms, dp = 0) => {
  let timeScalarIndex = 0, scaledTime = ms;

  while (scaledTime > timeScalars[timeScalarIndex]) {
    scaledTime /= timeScalars[timeScalarIndex++];
  }

  return `${scaledTime.toFixed(dp)} ${timeUnits[timeScalarIndex]}`;
};

Example outputs:

getHumanReadableTime(512000);
getHumanReadableTime(5120000);
getHumanReadableTime(51200000);
getHumanReadableTime(51200000, 2);
getHumanReadableTime(51200000, 6);

/*

Output:
    '9 min'
    '1 hrs'
    '14 hrs'
    '14.22 hrs'
    '14.222222 hrs'

*/
Nick Bull
  • 9,518
  • 6
  • 36
  • 58
3
function millisecondsToString(milliseconds) {
    var oneHour = 3600000;
    var oneMinute = 60000;
    var oneSecond = 1000;
    var seconds = 0;
    var minutes = 0;
    var hours = 0;
    var result;

    if (milliseconds >= oneHour) {
        hours = Math.floor(milliseconds / oneHour);
    }

    milliseconds = hours > 0 ? (milliseconds - hours * oneHour) : milliseconds;

    if (milliseconds >= oneMinute) {
        minutes = Math.floor(milliseconds / oneMinute);
    }

    milliseconds = minutes > 0 ? (milliseconds - minutes * oneMinute) : milliseconds;

    if (milliseconds >= oneSecond) {
        seconds = Math.floor(milliseconds / oneSecond);
    }

    milliseconds = seconds > 0 ? (milliseconds - seconds * oneSecond) : milliseconds;

    if (hours > 0) {
        result = (hours > 9 ? hours : "0" + hours) + ":";
    } else {
        result = "00:";
    }

    if (minutes > 0) {
        result += (minutes > 9 ? minutes : "0" + minutes) + ":";
    } else {
        result += "00:";
    }

    if (seconds > 0) {
        result += (seconds > 9 ? seconds : "0" + seconds) + ":";
    } else {
        result += "00:";
    }

    if (milliseconds > 0) {
        result += (milliseconds > 9 ? milliseconds : "0" + milliseconds);
    } else {
        result += "00";
    }

    return result;
}
Obaluaiyê
  • 83
  • 1
  • 5
3

Here is my take.

Feel free to play around with it in the jsbin.

// This returns a string representation for a time interval given in milliseconds
// that appeals to human intuition and so does not care for leap-years,
// month length irregularities and other pesky nuisances.
const human_millis = function (ms, digits=1) {
    const levels=[
      ["ms", 1000],
      ["sec", 60],
      ["min", 60],
      ["hrs", 24],
      ["days", 7],
      ["weeks", (30/7)], // Months are intuitively around 30 days
      ["months", 12.1666666666666666], // Compensate for bakari-da in last step
      ["years", 10],
      ["decades", 10],
      ["centuries", 10],
      ["millenia", 10],
    ];
    var value=ms;
    var name="";
    var step=1;
    for(var i=0, max=levels.length;i<max;++i){
        value/=step;
        name=levels[i][0];
        step=levels[i][1];
        if(value < step){
            break;
        }
    }
    return value.toFixed(digits)+" "+name;
}

console.clear();
console.log("---------");
console.log(human_millis(1));
console.log(human_millis(10));
console.log(human_millis(100));
console.log(human_millis(1000));
console.log(human_millis(1000*60));
console.log(human_millis(1000*60*60));
console.log(human_millis(1000*60*60*24));
console.log(human_millis(1000*60*60*24*7));
console.log(human_millis(1000*60*60*24*30));
console.log(human_millis(1000*60*60*24*365));
console.log(human_millis(1000*60*60*24*365*10));
console.log(human_millis(1000*60*60*24*365*10*10));
console.log(human_millis(1000*60*60*24*365*10*10*10));
console.log(human_millis(1000*60*60*24*365*10*10*10*10));

If you use Typescript type and cast to make it work

let name : string | number = "";
    let step : string | number =1;
    for(var i=0, max=levels.length;i<max;++i){
        value/= step as number;
        name=levels[i][0];
        step=levels[i][1];
        if(value < step){
            break;
        }
        
    }

Output:

"---------"
"1.0 ms"
"10.0 ms"
"100.0 ms"
"1.0 sec"
"1.0 min"
"1.0 hrs"
"1.0 days"
"1.0 weeks"
"1.0 months"
"1.0 years"
"1.0 decades"
"1.0 centuries"
"1.0 millenia"
"10.0 millenia"
BorisD
  • 1,611
  • 17
  • 22
Mr. Developerdude
  • 9,118
  • 10
  • 57
  • 95
2

This function outputs seconds in this format : 11h 22m, 1y 244d, 42m 4s etc Set the max variable to show as many identifiers as you want.

function secondsToString (seconds) {

var years = Math.floor(seconds / 31536000);
var max =2;
var current = 0;
var str = "";
if (years && current<max) {
    str+= years + 'y ';
    current++;
}
var days = Math.floor((seconds %= 31536000) / 86400);
if (days && current<max) {
    str+= days + 'd ';
    current++;
}
var hours = Math.floor((seconds %= 86400) / 3600);
if (hours && current<max) {
    str+= hours + 'h ';
    current++;
}
var minutes = Math.floor((seconds %= 3600) / 60);
if (minutes && current<max) {
    str+= minutes + 'm ';
    current++;
}
var seconds = seconds % 60;
if (seconds && current<max) {
    str+= seconds + 's ';
    current++;
}

return str;
}
Kiran Kumar
  • 1,192
  • 8
  • 10
2

With the help of Dan answer, I came up with this if you want to calculate the difference between the post created time (from DB it should be retrieved as UTC) and the users system time and then show them the elapsed time, you could use below function

function dateToStr(input_date) {
  input_date= input_date+" UTC";
  // convert times in milliseconds
  var input_time_in_ms = new Date(input_date).getTime();
  var current_time_in_ms = new Date().getTime();
  var elapsed_time = current_time_in_ms - input_time_in_ms;

  function numberEnding (number) {
      return (number > 1) ? 's' : '';
  }

  var temp = Math.floor(elapsed_time / 1000);
  var years = Math.floor(temp / 31536000);
  if (years) {
      return years + ' year' + numberEnding(years);
  }
  //TODO: Months! Maybe weeks? 
  var days = Math.floor((temp %= 31536000) / 86400);
  if (days) {
      return days + ' day' + numberEnding(days);
  }
  var hours = Math.floor((temp %= 86400) / 3600);
  if (hours) {
      return hours + ' hour' + numberEnding(hours);
  }
  var minutes = Math.floor((temp %= 3600) / 60);
  if (minutes) {
      return minutes + ' minute' + numberEnding(minutes);
  }
  var seconds = temp % 60;
  if (seconds) {
      return seconds + ' second' + numberEnding(seconds);
  }
  return 'less than a second'; //'just now' //or other string you like;
}

eg: usage

var str = dateToStr('2014-10-05 15:22:16');
Eddie
  • 53,828
  • 22
  • 125
  • 145
santoshthota
  • 303
  • 1
  • 3
  • 10
2

There is the Intl.RelativeTimeFormat API, which is supported in recent versions of Chrome and Firefox.

An few examples:

let rtf = new Intl.RelativeTimeFormat("en");
rtf.format(-1, "day"); // 'yesterday'
rtf.format(-2, 'day'); // '2 days ago'
rtf.format(13.37, 'second'); // 'in 13.37 seconds'

And there's a lot more in this blog post and in the proposal itself.

1

To show only what you need and not day 0, hours 0...

formatTime = function(time) {
        var ret = time % 1000 + ' ms';
        time = Math.floor(time / 1000);
        if (time !== 0) {
            ret = time % 60 + "s "+ret;
            time = Math.floor(time / 60);
            if (time !== 0) {
                ret = time % 60 + "min "+ret;
                time = Math.floor(time / 60);
                if (time !== 0) {
                    ret = time % 60 + "h "+ret;
                     ...
                }
            }           
        }
        return ret;
    };
Goofyrocks
  • 153
  • 1
  • 9
  • I love it. It returns only part that are used (bigger than zero). btw. You cold remove space before "ms" cause other units don't have space before them. – hrvoj3e Mar 08 '14 at 20:12
1

Following a similar approach to @Dan, I have modified @Royi Namir's code to output a string with commas and and's:

secondsToString = function(seconds) {
    var numdays, numhours, nummilli, numminutes, numseconds, numyears, res;
    numyears = Math.floor(seconds / 31536000);
    numdays = Math.floor(seconds % 31536000 / 86400);
    numhours = Math.floor(seconds % 31536000 % 86400 / 3600);
    numminutes = Math.floor(seconds % 31536000 % 86400 % 3600 / 60);
    numseconds = seconds % 31536000 % 86400 % 3600 % 60;
    nummilli = seconds % 1.0;
    res = [];
    if (numyears > 0) {
        res.push(numyears + " years");
    }
    if (numdays > 0) {
        res.push(numdays + " days");
    }
    if (numhours > 0) {
        res.push(numhours + " hours");
    }
    if (numminutes > 0) {
        res.push(numminutes + " minutes");
    }
    if (numseconds > 0) {
        res.push(numseconds + " seconds");
    }
    if (nummilli > 0) {
        res.push(nummilli + " milliseconds");
    }
    return [res.slice(0, -1).join(", "), res.slice(-1)[0]].join(res.length > 1 ? " and " : "");
};

It has no period so one can add sentences after it, like here:

perform: function(msg, custom, conn) {
    var remTimeLoop;
    remTimeLoop = function(time) {
        if (time !== +custom[0]) {
            msg.reply((secondsToString(time)) + " remaining!");
        }
        if (time > 15) {
            return setTimeout((function() {
                return remTimeLoop(time / 2);
            }), time / 2);
        }
    };
    // ...
    remTimeLoop(+custom[0]);
}

Where custom[0] is the total time to wait for; it will keep dividing the time by 2, warning the time remaining until the timer ends, and stop warning once the time is under 15 seconds.

dystopiandev
  • 134
  • 1
  • 6
wallabra
  • 412
  • 8
  • 17
1

Below will work for both past and future datetime, also have option to pass locale.

function relativeTime(isoString, locale = "en") {
  const timestamp = Date.parse(isoString);
  const msPerMinute = 60 * 1000;
  const msPerHour = msPerMinute * 60;
  const msPerDay = msPerHour * 24;
  const msPerMonth = msPerDay * 30;
  const msPerYear = msPerDay * 365;

  const current = Date.now();
  let elapsed = current - timestamp;

  const sign = elapsed > 0 ? -1 : 1;

  elapsed = Math.abs(elapsed);

  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });

  if (elapsed < msPerMinute) {
    return rtf.format(sign * Math.floor(elapsed / 1000), "seconds");
  } else if (elapsed < msPerHour) {
    return rtf.format(sign * Math.floor(elapsed / msPerMinute), "minutes");
  } else if (elapsed < msPerDay) {
    return rtf.format(sign * Math.floor(elapsed / msPerHour), "hours");
  } else if (elapsed < msPerMonth) {
    return rtf.format(sign * Math.floor(elapsed / msPerDay), "days");
  } else if (elapsed < msPerYear) {
    return rtf.format(sign * Math.floor(elapsed / msPerMonth), "months");
  } else {
    return new Date(timestamp).toLocaleString(locale);
  }
}

Output:

relativeTime(new Date().toISOString()) //'2021-11-13T18:48:58.243Z'
-> now

relativeTime('2021-11-13T18:48:50.243Z')
-> 8 seconds ago

relativeTime('2021-11-14T18:48:50.243Z')
-> in 23 hours

relativeTime('2021-11-15T18:48:50.243Z')
-> tomorrow

relativeTime('2021-10-15T18:48:50.243Z')
-> 29 days ago

relativeTime('2021-12-15T18:48:50.243Z')
-> next month

GorvGoyl
  • 42,508
  • 29
  • 229
  • 225
1

Here's a simple implementation:

function formatDuration(seconds) {
  const time = {
    d: Math.floor(seconds / 86400),
    h: Math.floor(seconds / 3600) % 24,
    m: Math.floor(seconds / 60) % 60,
    s: seconds % 60,
  };

  return Object.entries(time).filter(val => val[1] !== 0).map(val => val[1] + val[0]).join('');
}

In use it will produce this:

>  formatDuration(65_535)
<• '18h12m15s'
jeffdill2
  • 3,968
  • 2
  • 30
  • 47
0

This is a solution. Later you can split by ":" and take the values of the array

 /**
 * Converts milliseconds to human readeable language separated by ":"
 * Example: 190980000 --> 2:05:3 --> 2days 5hours 3min
 */
function dhm(t){
    var cd = 24 * 60 * 60 * 1000,
        ch = 60 * 60 * 1000,
        d = Math.floor(t / cd),
        h = '0' + Math.floor( (t - d * cd) / ch),
        m = '0' + Math.round( (t - d * cd - h * ch) / 60000);
    return [d, h.substr(-2), m.substr(-2)].join(':');
}

//Example
var delay = 190980000;                   
var fullTime = dhm(delay);
console.log(fullTime);
Peter
  • 13,733
  • 11
  • 75
  • 122
ssamuel68
  • 932
  • 13
  • 10
0

I'm a big fan of objects, so I created this from https://metacpan.org/pod/Time::Seconds

Usage:

var human_readable = new TimeSeconds(986543).pretty(); // 11 days, 10 hours, 2 minutes, 23 seconds

;(function(w) {
  var interval = {
    second: 1,
    minute: 60,
    hour: 3600,
    day: 86400,
    week: 604800,
    month: 2629744, // year / 12
    year: 31556930 // 365.24225 days
  };

  var TimeSeconds = function(seconds) { this.val = seconds; };

  TimeSeconds.prototype.seconds = function() { return parseInt(this.val); };
  TimeSeconds.prototype.minutes = function() { return parseInt(this.val / interval.minute); };
  TimeSeconds.prototype.hours = function() { return parseInt(this.val / interval.hour); };
  TimeSeconds.prototype.days = function() { return parseInt(this.val / interval.day); };
  TimeSeconds.prototype.weeks = function() { return parseInt(this.val / interval.week); };
  TimeSeconds.prototype.months = function() { return parseInt(this.val / interval.month); };
  TimeSeconds.prototype.years = function() { return parseInt(this.val / interval.year); };

  TimeSeconds.prototype.pretty = function(chunks) {
    var val = this.val;
    var str = [];

    if(!chunks) chunks = ['day', 'hour', 'minute', 'second'];

    while(chunks.length) {
      var i = chunks.shift();
      var x = parseInt(val / interval[i]);
      if(!x && chunks.length) continue;
      val -= interval[i] * x;
      str.push(x + ' ' + (x == 1 ? i : i + 's'));
    }

    return str.join(', ').replace(/^-/, 'minus ');
  };

  w.TimeSeconds = TimeSeconds;
})(window);
0

I cleaned up one of the other answers a bit provides nice '10 seconds ago' style strings:

function msago (ms) {
    function suffix (number) { return ((number > 1) ? 's' : '') + ' ago'; }
    var temp = ms / 1000;
    var years = Math.floor(temp / 31536000);
    if (years) return years + ' year' + suffix(years);
    var days = Math.floor((temp %= 31536000) / 86400);
    if (days) return days + ' day' + suffix(days);
    var hours = Math.floor((temp %= 86400) / 3600);
    if (hours) return hours + ' hour' + suffix(hours);
    var minutes = Math.floor((temp %= 3600) / 60);
    if (minutes) return minutes + ' minute' + suffix(minutes);
    var seconds = Math.floor(temp % 60);
    if (seconds) return seconds + ' second' + suffix(seconds);
    return 'less then a second ago';
};
Adrian Seeley
  • 2,262
  • 2
  • 29
  • 37
0
function java_seconds_to_readable(seconds)
{
    var numhours = Math.floor(seconds / 3600);
    var numminutes = Math.floor((seconds / 60) % 60);
    var numseconds = seconds % 60;
    return numhours + ":" + numminutes + ":" + numseconds;
}

More simple way. You can years and days respectively.

Faisal Shahzad
  • 694
  • 9
  • 13
0

if you use node :

const humanize = require('human-date');

let yesterday = new Date(new Date().setDate(new Date().getDate()-1));

console.log(humanize.relativeTime(yesterday)); //=> 1 day ago
Syscall
  • 19,327
  • 10
  • 37
  • 52
Ali
  • 1
0

Since moment.js is deprecated since 2020, a useful currently maintained library for this would be humanize-duration.

codeflorist
  • 334
  • 3
  • 11
-1
function secondsToTimeString(input) {
  let years = 0, days = 0, hours = 0, minutes = 0, seconds = 0;
  let ref = [31536000,86400,3600,60,1];
  for (let i = 0;i < ref.length;i++) {
    let val = ref[i];
    while (val <= input) {
      input -= val;
      if (i === 0) years++;
      if (i === 1) days++;
      if (i === 2) hours++;
      if (i === 3) minutes++;      
      if (i === 4) seconds++;      
    }
  return {years, days, hours, minutes, seconds};
  }
onlyphantom
  • 8,606
  • 4
  • 44
  • 58
Tahir
  • 1
  • 1