144

I am having similar requirement as this: Convert time in HH:MM:SS format to seconds only?

but in javascript. I have seen many examples of converting seconds into different formats but not HH:MM:SS into seconds.

Francesco - FL
  • 603
  • 1
  • 4
  • 25
Sri Reddy
  • 6,832
  • 20
  • 70
  • 112

16 Answers16

256

Try this:

var hms = '02:04:33';   // 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);
Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
  • 6
    Here's a prototype version of this! `String.prototype.toSeconds = function () { if (!this) return null; var hms = this.split(':'); return (+hms[0]) * 60 * 60 + (+hms[1]) * 60 + (+hms[2] || 0); }` NOTE: the `|| 0` at the end is good for any implementation of this code - it prevents issues with a (still valid) time representation of HH:MM (Chrome type="time" inputs will output in this format when seconds=0). – Fateh Khalsa May 06 '16 at 00:47
  • 8
    The use of "+" operator to convert numeric string to number is not a good idea. It's short and looks "clever", but it's confusing and not clean code. Use parseInt(x, 10) instead. And avoid one-liner. Also prevent errors by undefined input. For example: it's not a string, has no ":" or only "HH:MM". etc. – Dominik Sep 26 '17 at 14:09
91

This function handels "HH:MM:SS" as well as "MM:SS" or "SS".

function hmsToSecondsOnly(str) {
    var p = str.split(':'),
        s = 0, m = 1;

    while (p.length > 0) {
        s += m * parseInt(p.pop(), 10);
        m *= 60;
    }

    return s;
}
Niko
  • 26,516
  • 9
  • 93
  • 110
62

This can be done quite resiliently with the following:

'01:02:03'.split(':').reduce((acc,time) => (60 * acc) + +time);

This is because each unit of time within the hours, minutes and seconds is a multiple of 60 greater than the smaller unit. Time is split into hour minutes and seconds components, then reduced to seconds by using the accumulated value of the higher units multiplied by 60 as it goes through each unit.

The +time is used to cast the time to a number.

It basically ends up doing: (60 * ((60 * HHHH) + MM)) + SS

If only seconds is passed then the result would be a string, so to fix that we could cast the entire result to an int:

+('03'.split(':').reduce((acc,time) => (60 * acc) + +time));
Paul
  • 6,572
  • 2
  • 39
  • 51
  • thats actually pretty damn clever.. question is how fast this is compared to a calculation – ThatBrianDude Sep 20 '17 at 17:35
  • 5
    Yes it's clever, but a good example of creating difficult to maintain code for no practical gain. It saves 4 characters when minified vs a minified version of the accepted answer. Given that many web pages are now in excess of 1MB, that saving is somewhat less than insignificant. – RobG May 19 '18 at 09:24
  • 8
    Although this answer isn't as comprehensible, it does gracefully handle both `HH:MM:SS` as well as `MM:SS`, while the accepted answer does not. – ckeeney Aug 31 '18 at 18:45
  • 2
    This one has a type conversion bug, if there only the seconds portion is given. You need to explicit inititlise the memo with 0 to prevent it. Works: `'03'.split(':').reduce((acc,time) => (60 * acc) + +time, 0);` Fails because returns an unexpected string: `'03'.split(':').reduce((acc,time) => (60 * acc) + +time);` – Felix Gertz Mar 16 '19 at 10:35
  • @FelixGertz Well spotted, I'll edit in a fix for that case. – Paul Mar 18 '19 at 00:22
  • With @FelixGertz fix, this answer also handles milliseconds. `e.g. (1) '1:1:6.890' => 3666.89 (2) '.890' => 0.89`. – Venkata Raju Apr 08 '19 at 20:56
  • This answer also handles 60 hour days, and 60 day months. `MM:DD:HH:MM:SS` – squarecandy Apr 07 '20 at 21:22
  • @squarecandy Yes, interesting point. I believe the `:` as a separator is a good way to indicate that it is a unit of 60 (as in minutes and seconds). Once you get to days and months you are probably wanting to compare Date objects as you are no longer dealing with an elapsed time that has already been calculated. – Paul Apr 08 '20 at 02:34
  • I like this answer because I can tell right away that the code is correct. – ipid Nov 10 '20 at 05:00
  • @Paul My time input is in '2 h 10 m' format. How can I convert this into seconds? – Khadija Daruwala Jan 07 '22 at 08:43
  • 1
    @KhadijaDaruwala You can split the string by your separator `(space)` `'2 h 10 m'.split(' ')` to make it an array, access the correct offsets, multiply by the units (seonds in an hour, seconds in a minute), and add. – Paul Jan 11 '22 at 02:37
16

Since the getTime function of the Date object gets the milliseconds since 1970/01/01, we can do this:

var time = '12:23:00';
var seconds = new Date('1970-01-01T' + time + 'Z').getTime() / 1000;
boskop
  • 501
  • 6
  • 8
  • 1
    Just realized, this doesnt work with daylight savings time. Need to use the actual date – Yablargo Jun 13 '13 at 03:08
  • 2
    @Yablargo Thanks. Previous version didn't work very well with local timezone, so i edited it to use iso 8601 utc datetime format. – boskop Jul 15 '13 at 10:30
15

Convert hh:mm:ss string to seconds in one line. Also allowed h:m:s format and mm:ss, m:s etc

'08:45:20'.split(':').reverse().reduce((prev, curr, i) => prev + curr*Math.pow(60, i), 0)
B001ᛦ
  • 2,036
  • 6
  • 23
  • 31
Paul Hide
  • 166
  • 1
  • 3
  • 4
    Please explain your answer – B001ᛦ Nov 10 '16 at 13:43
  • Convert `hh:mm:ss` string to seconds in one line. Also allowed `h:m:s` format and `mm:ss`, `m:s` etc. – Paul Hide Nov 25 '16 at 12:56
  • Nice answer! But you could skip the `reverse()`: '00:01:11'.split(':').reduce((val, entry, i) => val + entry * (3600/Math.pow(60, i)), 0) === 71 – CMR Jan 07 '17 at 20:55
  • @CMR, interesting aproach, but in case of `mm:ss` it will not work correctly. – Paul Hide Jan 09 '17 at 13:43
  • Math.pow is very slow and can be avoided as shown in other answers based on reduce – Alejadro Xalabarder May 03 '20 at 13:57
  • If you are going to call this more than a couple of times, you can use a lookup table to avoid Math.pow. For example `const powersOf60LUT = [1, 60, 3600];` would be enough for hh:mm:ss. You just have to replace the Math.pow block with `powersOf60LUT[i]` – Enrico Aug 10 '20 at 02:02
  • @PaulHide My time input is in '2 h 10 m' format. How can I convert this into seconds? – Khadija Daruwala Jan 07 '22 at 08:43
13

This is the most clear, easy to understand solution:

function convertDurationtoSeconds(duration){
    const [hours, minutes, seconds] = duration.split(':');
    return Number(hours) * 60 * 60 + Number(minutes) * 60 + Number(seconds);
};

const input = '01:30:45';
const output = convertDurationtoSeconds(input);
console.log(`${input} is ${output} in seconds`);
Melchia
  • 22,578
  • 22
  • 103
  • 117
10

try

time="12:12:12";
tt=time.split(":");
sec=tt[0]*3600+tt[1]*60+tt[2]*1;
Luca
  • 4,223
  • 1
  • 21
  • 24
7

Here is maybe a bit more readable form on the original approved answer.

const getSeconds = (hms: string) : number => {
  const [hours, minutes, seconds] = hms.split(':');
  return (+hours) * 60 * 60 + (+minutes) * 60 + (+seconds);
};
Jan Vorcak
  • 19,261
  • 14
  • 54
  • 90
  • 2
    You should mention that this is *TYPESCRIPT*, and __WON'T WORK__ if you copy and paste this as VANILLA JAVASCRIPT. – Jack_Hu Feb 26 '22 at 00:50
5

Javascript's static method Date.UTC() does the trick:

alert(getSeconds('00:22:17'));

function getSeconds(time)
{
    var ts = time.split(':');
    return Date.UTC(1970, 0, 1, ts[0], ts[1], ts[2]) / 1000;
}
Chronozoa
  • 310
  • 6
  • 10
  • Nice trick with `Date.UTC()`, though note that this does assume that there are always two colons in the string, so parsing `"12:42"` wouldn't work without additional handling. – jdunning Mar 13 '23 at 00:01
2
new Date(moment('23:04:33', "HH:mm")).getTime()

Output: 1499755980000 (in millisecond) ( 1499755980000/1000) (in second)

Note : this output calculate diff from 1970-01-01 12:0:0 to now and we need to implement the moment.js

ITsDEv
  • 51
  • 3
1

This function works for MM:SS as well:

const convertTime = (hms) => {
        if (hms.length <3){
         return hms
        } else if (hms.length <6){
          const a = hms.split(':')
          return hms = (+a[0]) * 60 + (+a[1])
        } else {
          const a = hms.split(':')
          return hms = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2])
        }
      }
1

Taken from the solution given by Paul https://stackoverflow.com/a/45292588/1191101 but using the old function notation so it can also be used in other js engines (e.g. java Rhino)

function strToSeconds (stime)
{
   return +(stime.split(':').reduce(function (acc,time) { return +(60 * acc) + +time }));
}

or just this one more readable

function strToSeconds (stime)
{
  var tt = stime.split(':').reverse ();
  return ((tt.length >= 3) ? (+tt[2]): 0)*60*60 + 
         ((tt.length >= 2) ? (+tt[1]): 0)*60 + 
         ((tt.length >= 1) ? (+tt[0]): 0);
}
Alejadro Xalabarder
  • 1,551
  • 19
  • 14
0

I would suggest a slightly different approach to most other answers here:

// Solution:
const hmsToSeconds = s => /^\d+:\d+:\d+$/.test(s) ? s.split(':').reduce((x, y) => x * 60 | y) : NaN;


// Test cases to check correctness:
`0:0:0
0:0:1
0:1:0
1:0:0
1:1:1
1:1
1
:1:1
1:1:f
foo`
.split('\n')
.forEach(s => console.log(`${s} = ${hmsToSeconds(s)}`));

This isn't just because it's fun to write your own little one-liner; I believe this is probably a safer option than the other answers most of the time.

There is a dangerous flaw in the logic behind the several answers saying e.g. 'this code will also handle mm:ss and ss!', in that it confidently assumes that when it consumes, say, '13:37' that it should be reading '13 minutes & 37 seconds', rather than '23 minutes to 2'.

The opposite assumption would probably be the safer bet, I would personally have though. But ultimately it is best to not make any assumptions without actual solid basis in the actual sources of data the specific system is going to encounter. The last thing you want is a bad assumption like this in a tiny snippet of code buried deep in your codebase to go off like a landmine when months down the line data from a slightly different source starts failing silently.

This solution should pretty confidently reject anything not in the exact form '<int>:<int>:<int>' and just evaluate to NaN. This is likely to be noticed much sooner than the system (potentially intermittently!) be off in some calculations by a factor of 60.

Joey Sabey
  • 1,058
  • 7
  • 9
0

This is very old question, but here is two liner very easy to understand answer and it works with any of the following format

  • hh:mm:ss or h:m:s

  • mm:ss or m:s

  • ss or s

    function convertToSecs =(strTime){
        let [s=0, m=0, h=0] = strTime.split(':').reverse();
        return (+h) * 3600 + (+m) * 60 + (+s); 
    };
    
Niel
  • 66
  • 6
-1

function parsehhmmsst(arg) {
 var result = 0, arr = arg.split(':')
 if (arr[0] < 12) {
  result = arr[0] * 3600 // hours
 }
 result += arr[1] * 60 // minutes
 result += parseInt(arr[2]) // seconds
 if (arg.indexOf('P') > -1) {  // 8:00 PM > 8:00 AM
  result += 43200
 }
 return result
}
$('body').append(parsehhmmsst('12:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('1:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('2:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('3:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('4:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('5:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('6:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('7:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('8:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('9:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('10:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('11:00:00 AM') + '<br>')
$('body').append(parsehhmmsst('12:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('1:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('2:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('3:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('4:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('5:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('6:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('7:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('8:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('9:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('10:00:00 PM') + '<br>')
$('body').append(parsehhmmsst('11:00:00 PM') + '<br>')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Phillip Senn
  • 46,771
  • 90
  • 257
  • 373
-1

You can do this dynamically - in case you encounter not only: HH:mm:ss, but also, mm:ss, or even ss alone.

var str = '12:99:07';
var times = str.split(":");
times.reverse();
var x = times.length, y = 0, z;
for (var i = 0; i < x; i++) {
    z = times[i] * Math.pow(60, i);
    y += z;
}
console.log(y);
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Jeffz
  • 2,075
  • 5
  • 36
  • 51