86

I have a count of seconds stored in variable seconds. I want to convert for example 1439 seconds to 23 minutes and 59 seconds. And if the time is greater than 1 hour (for example 9432 seconds), to 2 hours, 37 minutes and 12 seconds.

How can I achieve this?

I'm thinking of:

var sec, min, hour;

if(seconds<3600){
    var a = Math.floor(seconds/60); //minutes
    var b = seconds%60; //seconds

    if (b!=1){
        sec = "seconds";
    }else{
        sec = "second";
    }

    if(a!=1){
        min = "minutes";
    }else{
        min = "minute";
    }

    $('span').text("You have played "+a+" "+min+" and "+b+" "+sec+".");
}else{
        var a = Math.floor(seconds/3600); //hours
    var x = seconds%3600;
    var b = Math.floor(x/60); //minutes
    var c = seconds%60; //seconds

     if (c!=1){
        sec = "seconds";
    }else{
        sec = "second";
    }

    if(b!=1){
        min = "minutes";
    }else{
        min = "minute";
    }

    if(c!=1){
        hour = "hours";
    }else{
        hour = "hour";
    }

    $('span').text("You have played "+a+" "+hour+", "+b+" "+min+" and "+c+" "+sec+".");
}

But that's a lot of code, and it has to be calculated each second. How can I shrink this up?

ALSD Minecraft
  • 1,421
  • 3
  • 12
  • 18
  • 1
    I answered this here: [how to convert minutes to days,hours,minutes](http://stackoverflow.com/questions/2751073/how-to-convert-minutes-to-days-hours-minutes/2751143#2751143) – Romain Hippeau May 08 '16 at 05:02
  • @RomainHippeau hi! Yes, my code works, but it really big, I'm looking to a way to shrink it (: – ALSD Minecraft May 08 '16 at 05:04
  • you can use some library such as dateformat. – Kai Hao May 08 '16 at 05:05
  • Are you worried that it's large, or that it's slow? If the former, you can do a bit of refactoring and use a minifier; if the latter, it is really not slow: worrying about doing this each second is like worrying you shouldn't toss your bubblegum into trash because the junkyard might run out of space. – Amadan May 08 '16 at 05:07
  • @Amadan If it isn't slow then great! I want to shrink it because it's too large, just to make it more compact and use less space, but I don't want to minify it. I'm really bad with shorthands but I was aiming towards that! – ALSD Minecraft May 08 '16 at 05:13
  • I'm voting to close this question as off-topic because it is asking for code review. – Felix Kling May 08 '16 at 05:53
  • Stack Overflow is primarily for question about problems with code (i.e. the code doesn't work), not for improving working code. – Felix Kling May 08 '16 at 05:54
  • Does this answer your question? [Converting seconds into HH:MM:SS](https://stackoverflow.com/questions/5539028/converting-seconds-into-hhmmss) – Vega Sep 17 '20 at 13:10

20 Answers20

249

I think you would find this solution very helpful.

You modify the display format to fit your needs with something like this -

function secondsToHms(d) {
    d = Number(d);
    var h = Math.floor(d / 3600);
    var m = Math.floor(d % 3600 / 60);
    var s = Math.floor(d % 3600 % 60);

    var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
    var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
    var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
    return hDisplay + mDisplay + sDisplay; 
}
Community
  • 1
  • 1
Wilson Lee
  • 2,631
  • 1
  • 10
  • 6
  • This is great! What are the statements used to get the display strings called? ('h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : ""') – Brandon Pillay Dec 27 '18 at 08:46
  • 3
    Hi @BrandonPillay - not sure if you've researched or not, but those statements are ternary operations: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator – swatkins Feb 21 '19 at 14:38
  • Using this code, passing in 0 returns a blank string, 60 returns `1 minute, `, and 3600 returns `1 hour, ` – Adam Taylor Feb 12 '20 at 18:11
  • 2
    I have made some adjustment for commas & time abbreviations: `function secondsToHms(d) { d = Number(d); var h = Math.floor(d / 3600); var m = Math.floor(d % 3600 / 60); var s = Math.floor(d % 3600 % 60); var hDisplay = h > 0 ? h + (h == 1 ? " hr" : " hrs") + (m > 0 || s > 0 ? ", ":"") : ""; var mDisplay = m > 0 ? m + (m == 1 ? " min" : " mins") + (s > 0 ? ", ":"") : ""; var sDisplay = s > 0 ? s + (s == 1 ? " sec" : " secs") : ""; return hDisplay + mDisplay + sDisplay; }` – ßikrant Giri Oct 29 '20 at 11:29
  • Based on ßikrant's, I have taken the liberty of also adding the DAYS: function sec2dhms(x) {x=Number(x); var d=Math.floor(x / (24*3600)); var h=Math.floor(x % (3600*24) / 3600 ); var m=Math.floor(x % 3600 / 60); var s=Math.floor(x % 3600 % 60); var dDisplay=d>0? d + (d==1? " day" : " days") + (h>0 || m > 0 || s > 0 ? ", ":"") : ""; var hDisplay=h>0? h + (h==1? " hr" : " hrs") + (m > 0 || s > 0 ? ", ":"") : ""; var mDisplay=m>0? m + (m==1? " min" : " mins") + (s > 0 ? ", ":"") : ""; var sDisplay=s>0? s + (s==1? " sec" : " secs") : ""; return dDisplay + hDisplay + mDisplay + sDisplay;} – sscalvo Dec 06 '22 at 14:50
27

The builtin JavaScript Date object can simplify the required code

 toTime(seconds) {
       var date = new Date(null);
       date.setSeconds(seconds);
       return date.toISOString().substr(11, 8);
    }
morganbaz
  • 2,997
  • 1
  • 17
  • 30
  • 1
    This seems to save a lot of code, are there drawbacks to using this method? Why are other answers preferred? – Stephan Luis Feb 17 '21 at 22:48
  • 1
    This MUST be the selected answer. No modules needed, as `Date` is standard, and it does the exact conversion requested. It seems that people know jQuery better than the language itself. – punund May 10 '21 at 23:28
  • 1
    This does not answer the ops question as to how to format seconds to come out looking like `2 hours, 17 minutes, 14 seconds`. It can't even be trivially used to cut out the pieces, since the resulting `02:17:14` string will have leading zeros (and roll over to all 0s at 24 hours). It's useful code and a good way to solve a similar problem, but if you came here looking for what the op was looking for, this will not help – Torque Dec 08 '21 at 09:00
  • 3
    this doesn't work if you have 24 hours or more – Alasdair McLeay May 11 '22 at 11:18
  • 1
    instead of extracting only parts of the iso string, you could use toLocaleTimeString and get only the parts you need: `return date.toLocaleTimeString('de-DE', {timeZone: 'UTC'})` – honk31 Jul 21 '22 at 12:47
  • Instead of `.substr(11, 8)` use `.slice(11, 19)` (or @honk31's suggestion). [`substr`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr) is deprecated. – Thomas Sep 12 '22 at 17:21
15

You can try this, i have used this successfully in the past You should be able to add the minutes and seconds on easily

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);

    var obj = {
        "h": hours,
        "m": minutes,
        "s": seconds
    };
    return obj;
}

Fiddle

You can change the object to

var obj = {
        "h": hours + " hours",
        "m": minutes + " minutes",
        "s": seconds + " seconds"
    };
R4nc1d
  • 2,923
  • 3
  • 24
  • 44
8

I'm probably a bit late but you can achieve this kind of things using

https://momentjs.com/

myVar = moment(myVar).format('HH:mm');

moment provides A LOT of format for hours / dates etc.

pkerckhove
  • 763
  • 2
  • 10
  • 17
  • 3
    Never too late, but I definitely think that depending on the use case you can add momentjs but just to add a whole library for something as small as this ... seems a bit much don't you think. But yes it will get the job done – R4nc1d Nov 28 '17 at 18:43
  • 3
    moment.js is great, but to format seconds instead of a moment object, you have to use `moment.duration()`. For example: `${moment.duration(Number(myVar), 'seconds').hours()}:${moment.duration(Number(myVar), 'seconds').minutes()}:${moment.duration(Number(myVar), 'seconds').seconds()}` – Sauce Mar 08 '18 at 15:41
  • This is great, but without specifiying the timezone it will add up offset ours, so you should go with: `moment.utc(myVar)...` – 4unkur Jan 01 '20 at 08:56
  • don't forget that the project authors of moment.js themselves broadly no longer recommend you use it: https://momentjs.com/docs/#/-project-status/ – Frikster Feb 08 '22 at 04:16
6

A low fat way to do this is:

function seconds_to_days_hours_mins_secs_str(seconds)
{ // day, h, m and s
  var days     = Math.floor(seconds / (24*60*60));
      seconds -= days    * (24*60*60);
  var hours    = Math.floor(seconds / (60*60));
      seconds -= hours   * (60*60);
  var minutes  = Math.floor(seconds / (60));
      seconds -= minutes * (60);
  return ((0<days)?(days+" day, "):"")+hours+"h, "+minutes+"m and "+seconds+"s";
}

Thus

> seconds_to_days_hours_mins_secs_str(9432+60*60*24)
'1 days, 2h, 37m and 12s'

This is easy to understand and extend as needed.

Brian
  • 494
  • 6
  • 8
6

Try this, Convert SEC to H:M:S.

function convertTime(sec) {
    var hours = Math.floor(sec/3600);
    (hours >= 1) ? sec = sec - (hours*3600) : hours = '00';
    var min = Math.floor(sec/60);
    (min >= 1) ? sec = sec - (min*60) : min = '00';
    (sec < 1) ? sec='00' : void 0;

    (min.toString().length == 1) ? min = '0'+min : void 0;    
    (sec.toString().length == 1) ? sec = '0'+sec : void 0;    

    return hours+':'+min+':'+sec;
}
Sushil
  • 2,324
  • 1
  • 27
  • 26
3

I found Wilson Lee's and Brian's code super useful! Here is how I adapted their code:

function formatTime(serverTimeinSeconds, elementId)
{ /* This converts seconds into days, hours, minutes and seconds timestring.
     Requires JQuery if elementId argument is provided */
  seconds = Math.floor(Number(serverTimeinSeconds));
  days = Math.floor(seconds / (24*60*60));
  seconds -= Math.floor(days    * (24*60*60));
  hours    = Math.floor(seconds / (60*60));
  seconds -= Math.floor(hours   * (60*60));
  minutes  = Math.floor(seconds / (60));
  seconds -= Math.floor(minutes * (60));

  dDisplay = days > 0 ? days + (days == 1 ? ' day, ' : ' days, ') : '';
  hDisplay = hours > 0 ? hours + (hours == 1 ? ' hour, ' : ' hours, ') : '';
  mDisplay = minutes > 0 ? minutes + (minutes == 1 ? ' minute, ' : ' minutes, ') : '';
  sDisplay = seconds > 0 ? seconds + (seconds == 1 ? ' second' : ' seconds') : '';

  if (elementId != null) {
    if (serverTimeinSeconds < 60) {
        $(elementId).css('font-size', '15px');
        $(elementId).html(sDisplay);
    }
    if (serverTimeinSeconds >= 60 && serverTimeinSeconds < 3600) {
        $(elementId).css('font-size', '15px');
        $(elementId).html(mDisplay + sDisplay);
    }
    if (serverTimeinSeconds >= 3600 && serverTimeinSeconds < 86400) {
        $(elementId).css('font-size', '12px');
        $(elementId).html(hDisplay + mDisplay + sDisplay);
    }
    if (serverTimeinSeconds >= 86400 && serverTimeinSeconds !== Infinity) {
        $(elementId).css('font-size', '8px');
        $(elementId).html(dDisplay + hDisplay + mDisplay + sDisplay);
    }
  }
  return dDisplay + hDisplay + mDisplay + sDisplay;
}
Brian
  • 494
  • 6
  • 8
David
  • 31
  • 4
3
 const formatter = (seconds = 0) => {
  const d = Number(secondsAmount);
  const h = Math.floor(d / 3600);
  const m = Math.floor((d % 3600) / 60);
  const s = Math.floor((d % 3600) % 60);
  const hDisplay = h > 0 ? `${h.toString().length > 1 ? `${h}` : `${0}${h}`}` : '00';
  const mDisplay = m > 0 ? `${m.toString().length > 1 ? `${m}` : `${0}${m}`}` : '00';
  const sDisplay = s > 0 ? `${s.toString().length > 1 ? `${s}` : `${0}${s}`}` : '00';
  return `${hDisplay}:${mDisplay}:${sDisplay}`;
};

Will return this format human readable format 00:00:00

user13782119
  • 129
  • 1
  • 4
3
Please install moment js after that import it,

import moment from 'moment'

let dateForm = (arg) => {
    return moment.unix(arg).utc().format('H [hours,] m [minutes and] s [seconds]');
}

console.log(dateForm(11));
// 0 hours, 0 minutes and 11 seconds

console.log(dateForm(16060)); // 1 hours, 0 minutes and 0 seconds

2

Built off R4nc1d's answer:

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

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

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

  return `${h?`${h}:`:""}${m?`${m}:${s}`:`${s}s`}`
}

This will return a human readable answer which looks like this. I used this for displaying the length of music tracks

time = secondsToTime(5)   
console.log(time)         // 5s
time = secondsToTime(50)  
console.log(time)         // 50s
time = secondsToTime(500) 
console.log(time)         // 8:20
time = secondsToTime(5000)
console.log(time)         // 1:23:20
2

for having the result with the time format " 00:00:00 " I added some changes to it.

function secondsToHms(seconds) {

  let d = Number(seconds);

  if(d <= 0){
     return '00:00:00'
  }else{
    let h = Math.floor(d / 3600);
    let m = Math.floor(d % 3600 / 60);
    let s = Math.floor(d % 3600 % 60);

    let hDisplay = h <= 9 ? '0'+ h+':' : h+ ":";
    let mDisplay = m <= 9 ? '0'+ m+':' : m+ ":";
    let sDisplay = s <= 9 ? '0'+ s : s;


    return hDisplay + mDisplay + sDisplay; 

  }}
1

@pkerckhove has already mentioned moment as a great library to work with dates and times, and you can also use moment to directly format the seconds into OP's desired format, i.e.:

import moment from 'moment'

const myVar = 1439
console.log(
    moment.unix(myVar).utc().format('H [hours,] m [minutes and] s [seconds]')
)

Will result in: 0 hours, 23 minutes and 59 seconds and,

import moment from 'moment'

const myVar = 9432
console.log(
    moment.unix(myVar).utc().format('H [hours,] m [minutes and] s [seconds]')
)

Will result in: 2 hours, 37 minutes and 12 seconds

thomaskleiven
  • 76
  • 1
  • 4
1

One way of doing it:

const formatDuration = totalSeconds => {
  const hours = Math.floor(totalSeconds / 3600)
  const minutes = Math.floor((totalSeconds % 3600) / 60)
  const seconds = totalSeconds - hours * 3600 - minutes * 60

  return [`${hours}h`, `${minutes}m`, `${seconds}s`]
    .filter(item => item[0] !== '0')
    .join(' ')
}
vedo27
  • 144
  • 1
  • 3
1

This method also works with a negative amount of time:

function CalculateTime(sec){

    if(sec >= 0){
        var h = Math.floor(sec / 3600);
    var m = Math.floor(sec % 3600 / 60);
    var s = Math.floor(sec % 3600 % 60);
    }
    else{
        var h = Math.ceil(sec / 3600);
    var m = Math.ceil(sec % 3600 / 60);
    var s = Math.ceil(sec % 3600 % 60);
    }

    var hDisplay = h !== 0 ? h + (h == 1 ? " hour, " : " hours") + (m != 0 || s > 0 ? ", ":"") : "";
    var mDisplay = m !== 0 ? m + (m == 1 ? " minute, " : " minutes")  + (s != 0 ? " ":""): "";
    var sDisplay = s !== 0 ? s + (s == 1 ? " second" : " seconds") : "";
    return hDisplay + mDisplay + sDisplay; 
}
lennart
  • 88
  • 6
0

Try this :D

secondsToHms(d) {
        d = Number(d);
        var h = Math.floor(d / 3600);
        var m = Math.floor(d % 3600 / 60);
        var s = Math.floor(d % 3600 % 60);

        var hDisplay = h > 0 ? h + (h == 1 ? "" : "") : "";
        var mDisplay = m > 0 ? m + (m == 1 ? "" : "") : "";
        var sDisplay = s > 0 ? s + (s == 1 ? "" : "") : "";
        if (hDisplay != "") {
            return (hDisplay.length > 1 ? hDisplay : '0' + hDisplay) + ":" + (mDisplay.length > 1 ? mDisplay : '0' + mDisplay) + ":" + (sDisplay.length > 1 ? sDisplay : '0' + sDisplay);
        }
        else if (mDisplay != "") {
            return (mDisplay.length > 1 ? mDisplay : '0' + mDisplay) + ":" + (sDisplay.length > 1 ? sDisplay : '0' + sDisplay);
        }
        else if (sDisplay != "") {
            return "00:" + (sDisplay.length > 1 ? sDisplay : '0' + sDisplay);
        }
        return "00:00"
    }
0

Using the popular date-fns library

import { format, setSeconds, startOfDay } from 'date-fns'

export const hourMinSec = (secs: number, showHour = false): string => {

  const tmpDate: Date = startOfDay(new Date())
  const date: Date = setSeconds(tmpDate, secs)
  const hour: number = date.getHours()
  const hasHour: boolean = !!hour

  if (hasHour && !showHour) console.warn('hourMinSec is hiding a non zero hour')

  const strFormat: string = showHour ? 'H:mm:ss' : 'm:ss'
  return format(date, strFormat)
}

OR the same code with a more functional approach (adding lodash flow in the mix)

import { setSeconds, startOfDay } from 'date-fns/fp'
import { format } from 'date-fns'
import { flow } from 'lodash-es'

export const hourMinSec = (secs: number, showHour = false): string => {
  const date: Date = flow(startOfDay, setSeconds(secs))(new Date())
  const hour: number = date.getHours()
  const hasHour: boolean = !!hour

  if (hasHour && !showHour) console.warn('hourMinSec is hiding a non zero hour')

  const strFormat: string = showHour ? 'H:mm:ss' : 'm:ss'
  return format(date, strFormat)
}

Usage:

hourMinSec(100)         //    1:40
hourMinSec(3700)        //    1:40 // will warn in logs that a non zero hour is hidden
hourMinSec(100, true)   // 0:01:40
hourMinSec(3700, true)  // 1:01:40

This met my needs but you could adapt this by changing the showHour = false parameter to be a strFormat = 'm:ss' parameter instead to support more flexible formatting.

danday74
  • 52,471
  • 49
  • 232
  • 283
0
const minutes = Math.floor(duration / 60);
const seconds = Math.floor(duration - minutes * 60);

const time = `${minutes < 10 ? `0${minutes}` : minutes}
             :${seconds < 10 ? `0${seconds}` : seconds}`; // result: 02:23
omid
  • 1
  • While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. You can find more information on how to write good answers in the help center: https://stackoverflow.com/help/how-to-answer . Good luck – nima Oct 07 '21 at 11:26
0

useCountDown Hook

// useCountDown.js

import { useEffect, useState } from "react"

const useCountDown = (minutes) => {
  const [seconds, setSeconds] = useState(minutes * 60)

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(seconds - 1)
    }, 1000)

    return () => clearInterval(interval)
  }, [seconds])

  return getReturnValues2(seconds)
}

const getReturnValues2 = (countDown) => {

  const minutes = Math.floor(countDown / 60)
  const seconds = countDown % 60

  return `${padTo2Digits(minutes)}:${padTo2Digits(seconds)}`
}

function padTo2Digits(num) {
  return num.toString().padStart(2, "0")
}

export default useCountDown

How to use?

//React Component

import useCountDown from '../hooks/useCountDown'

function App() {
   const countDown = useCountDown(5) // 5 Minutes
   return (
       <h1> {countDown} </h1>   // MM:SS
   )
}

You can tweak as per your needs.

Kanish
  • 273
  • 4
  • 10
0

Another option with inline comments:

// Seconds to Days Hours Minutes Seconds function
const sec2DHMS = s => {
  // D/Hr/Min from Sec calculation.
  // Both Hr and Min timeframes have 60 and D have 24 fractions, so we
  // can create one logic for them. We divide Min/Sec on 60 to find out
  // whole Hr/Min, then calculate Sec of whole Hr/Min, then calculate
  // difference between input Sec and Sec of whole Hr/Min to find out
  // fraction of Hr/Min. With D we do same thing, but with 24 divider.
  const calc = (v, f) => { const x = Math.trunc(v/f); return [x, v-x*f]; },
    [m, sr] = calc(s, 60),
    [h, mr] = calc(m, 60),
    [d, hr] = calc(h, 24);
  return { d, h, m, s, hr, mr, sr };
}

// Test all data
const { d, h, m, s, hr, mr, sr } = sec2DHMS(90061);
console.log(`${d} d, ${hr} hr, ${mr} min, ${sr} sec are whole ${h} hr, or ${m} min, or ${s} sec.`);

// So, if you need only Hr/Min/Sec
console.log(`90061 sec is ${h} hr, ${mr} min, ${sr} sec`);
tarkh
  • 2,424
  • 1
  • 9
  • 12
-2

Convert to H:M

Number(moment.duration(Number(37320), 'seconds').hours()+'.'+moment.duration(Number(37320),'seconds').minutes())