7

How can I sum time in javascript?

01:00:00
00:30:00
00:30:00

I have times like above I want the sum of the given time, like

sum of above time = 02:00:00

If I use the JavaScript methods setHours() and setMinutes() these function replace old time and show newly added time like:

  1. new Date(new Date(0, 0, 0, 00, 00, 00, 0)).setMinutes(30)
  2. new Date(new Date(new Date(0, 0, 0, 00, 00, 00, 0)).setMinutes(30)).setMinutes(30);

The result of both conditions the same but I want here 00:30 + 00:30 = 01:00.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Satnam singh
  • 205
  • 2
  • 3
  • 9

9 Answers9

11

Some functions to help you go back and forth between the formatted length of time and seconds as an integer:

function timestrToSec(timestr) {
  var parts = timestr.split(":");
  return (parts[0] * 3600) +
         (parts[1] * 60) +
         (+parts[2]);
}

function pad(num) {
  if(num < 10) {
    return "0" + num;
  } else {
    return "" + num;
  }
}

function formatTime(seconds) {
  return [pad(Math.floor(seconds/3600)),
          pad(Math.floor(seconds/60)%60),
          pad(seconds%60),
          ].join(":");
}

You can use them to achieve what you want:

time1 = "02:32:12";
time2 = "12:42:12";
formatTime(timestrToSec(time1) + timestrToSec(time2));
// => "15:14:24"
minikomi
  • 8,363
  • 3
  • 44
  • 51
7

Try this :

        var time1 = "01:00:00";
        var time2 = "00:30:00";
        var time3 = "00:30:00";
        
        var hour=0;
        var minute=0;
        var second=0;
        
        var splitTime1= time1.split(':');
        var splitTime2= time2.split(':');
        var splitTime3= time3.split(':');
        
        hour = parseInt(splitTime1[0])+parseInt(splitTime2[0])+parseInt(splitTime3[0]);
        minute = parseInt(splitTime1[1])+parseInt(splitTime2[1])+parseInt(splitTime3[1]);
        hour = hour + minute/60;
        minute = minute%60;
        second = parseInt(splitTime1[2])+parseInt(splitTime2[2])+parseInt(splitTime3[2]);
        minute = minute + second/60;
        second = second%60;
        
        alert('sum of above time= '+hour+':'+minute+':'+second);
Bhushan Kawadkar
  • 28,279
  • 5
  • 35
  • 57
  • 1
    This accepted answer is incorrect and only works for basic examples like that. You must convert first seconds to minutes and, after that, minutes to hours. Otherwise, you will get minutes greater than 60 in multiple cases. – daniherculano Oct 07 '22 at 07:49
4

If you want to use a Date object for this, you can, you just have to be sure to include the current value for the unit you're changing when adding to it, like so:

var dt = new Date(0, 0, 0, 0, 0, 0, 0);
dt.setHours(dt.getHours() + 1);      // For the 01:00
dt.setMinutes(dt.getMinutes() + 30); // For the first 00:30
dt.setMinutes(dt.getMinutes() + 30); // For the second 00:30

display("Hours: " + dt.getHours());
display("Minutes: " + dt.getMinutes());

function display(msg) {
  var p = document.createElement("p");
  p.innerHTML = String(msg);
  document.body.appendChild(p);
}

Technically, of course, the first time you know getHours and getMinutes will return 0, but for consistency, best to just always include them.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

This solution is perfect:

function timestrToSec(timestr) {
  var parts = timestr.split(":");
  return (parts[0] * 3600) +
         (parts[1] * 60) +
         (+parts[2]);
}

function pad(num) {
  if(num < 10) {
    return "0" + num;
  } else {
    return "" + num;
  }
}

function formatTime(seconds) {
  return [pad(Math.floor(seconds/3600)%60),
          pad(Math.floor(seconds/60)%60),
          pad(seconds%60),
          ].join(":");
}

but there is a little bug in the last function "formatTime" !

return [pad(Math.floor(seconds/3600)%60), => return [pad(Math.floor(seconds/3600)),

so without %60!! Becouse if i have to sum hour, it can be greater than 60 (H)

1

This work for me:

    function padnum(n){return n<10 ? '0'+n : n}

    var time1 = "00:30";
    var time2 = "00:60";

    var minute=0;
    var second=0;

    var splitTime1= time1.split(':');
    var splitTime2= time2.split(':');

    minute = parseInt(parseInt(splitTime1[0]))+parseInt(splitTime2[0]);
    second = parseInt(parseInt(splitTime1[1]))+parseInt(splitTime2[1]);

    minute = minute + second/60;
    minute =parseInt(minute);
    second = second%60;

    minute = padnum(minute);
    second = padnum(second);        

    alert('sum of above time= '+minute+':'+second);
0

Here is a function with error handling included.

Even though it's a big function it results in an useful one-liner. Just pass an array with values and you're good to go.

function sumMinutes(values) {

  const validate = time => {
    if (time > 59 || time < 0) {
      throw new Error(
        "Hours, minutes and seconds values have to be between 0 and 59."
      );
    }
    return time;
  };

  const seconds = values
    .map(e => validate(Number(e.split(":").reverse()[0])))
    .reduce((a, b) => a + b);

  let minutes = values
    .map(e => Number(e.split(":").reverse()[1]))
    .reduce((a, b) => a + b);

  let hours = values
    .map(e =>
      e.split(":").reverse()[2] ? Number(e.split(":").reverse()[2]) : 0
    )
    .reduce((a, b) => a + b);

  minutes *= 60;
  hours *= 3600;

  let result = new Date((hours + minutes + seconds) * 1000)
    .toISOString()
    .substr(11, 8);

  return result.split(":").reverse()[2] === "00" ? result.slice(3) : result;
}

/* examples */
const seconds = ["00:03", "00:9"];
const mins = ["01:20", "1:23"];
const hours = ["00:03:59", "02:05:01"];
const mix = ["00:04:58", "10:00"];

console.log(sumMinutes(seconds)); //'00:12'
console.log(sumMinutes(mins)); //'02:43'
console.log(sumMinutes(hours)); //'02:09:00'
console.log(sumMinutes(mix)); //'14:58'
Diego Fortes
  • 8,830
  • 3
  • 32
  • 42
0

Here how I handled, If you sum only hours, the function returns total hours and minutes, not days.

function timeToMins(time) {
    var b = time.split(':');
    return b[0] * 60 + +b[1];
};

function timeFromMins(mins) {
    function z(n) {
        if (n < 0) return ('-0' + (n).toString().slice(1));
        return (n < 10 ? '0' : '') + n;
    };

    var h = (mins / 60 | 0);
    var m = mins % 60;
    return z(h) + ':' + z(m);
};

function addTimes(time0, time1) {
    return timeFromMins(timeToMins(time0) + timeToMins(time1));
};

addTimes('02:30', '-00:30');

The output will be: 02:00

// Array [0] 01:00:00
// Array [1] 00:30:00
// Array [2] 00:30:00

let time = '01:00:00';
time = addTimes(time, '00:30:00');
time = addTimes(time, '00:30:00');

The output will be: 02:00
Premji
  • 69
  • 1
  • 6
0

I did it keeping things simple.

This is my approach:

function sumTime(time1, time2) {
    const splitTime1= time1.split(':');
    const splitTime2= time2.split(':');

    let hour = parseInt(splitTime1[0])+parseInt(splitTime2[0]);
    let minute = parseInt(splitTime1[1])+parseInt(splitTime2[1]);
    let second = parseInt(splitTime1[2])+parseInt(splitTime2[2]);
    // Fix seconds, example: 400:60:124 -> 400:62:04
    minute = minute + (Math.floor(second/60)); // 124 / 60 = 2.07 -> +2 minutes
    second = Math.floor(second%60) // 124 % 60 = 4 -> 4 seconds
    // Fix minutes, example: 400:62:04 -> 401:02:04
    hour = hour + (Math.floor(minute/60)) // 62 / 60 = 1.03 -> +1 hour
    minute = Math.floor(minute%60) // 62 % 60 = 2 -> 2 minutes

    // Formatting fields
    hour = hour.toString().padStart(2,'0');
    minute = minute.toString().padStart(2,'0');
    second = second.toString().padStart(2,'0');

    return `${hour}:${minute}:${second}`;
}
Aleix Soler
  • 91
  • 2
  • 7
0

Existing answers hardcode the hours minutes and seconds, but a dynamic approach is to split on the : delimiter and accumulate, multiplying each chunk by 60 and adding it to the next chunk. After doing this, the last element contains the total seconds, which can be converted to h:m:s.

const sumToSeconds = times => {
  return times.reduce((a, e) => {
    const parts = e.trim().split(":").map(Number);
    parts.forEach((e, i) => {
      if (i < parts.length - 1) {
        parts[i+1] += e * 60;
      }
    });
    return parts.pop() + a;
  }, 0);
};

const times = [
  "4:50",
  "2:02",
  "1:38",
  "2:49",
  "2:49",
  "2:13",
  "2:20",
  "2:12",
  "2:44",
  "4:23",
  "55:23",
  "1:01:02",
];
const totalSeconds = sumToSeconds(times);
console.log(
  `${~~(totalSeconds / 60 / 60)} hours, ${
     ~~((totalSeconds / 60) % 60)} minutes, ${
     ~~(totalSeconds % 60)} seconds`
); // => 2 hours, 24 minutes, 25 seconds

The h:m:s part can be made dynamic too, if desired:

const sumToSeconds = times => {
  return times.reduce((a, e) => {
    const parts = e.trim().split(":").map(Number);
    parts.forEach((e, i) => {
      if (i < parts.length - 1) {
        parts[i+1] += e * 60;
      }
    });
    return parts.pop() + a;
  }, 0);
};

const toHMS = time => {
  const labels = ["hours", "minutes", "seconds"];
  return Object.fromEntries(
    labels.map((e, i) => [
      e,
      ~~(time / 60 ** (labels.length - i - 1)) % 60,
    ])
  );
};

const times = [
  "4:50",
  "2:02",
  "1:38",
  "2:49",
  "2:49",
  "2:13",
  "2:20",
  "2:12",
  "2:44",
  "4:23",
  "55:23",
  "1:01:02",
];
console.log(toHMS(sumToSeconds(times)));
  // => { hours: 2, minutes: 24, seconds: 25 }

As an aside, if I may nitpick on your question a bit,

01:00:00
00:30:00
00:30:00

isn't a great test case to pick because it doesn't exercise the code thoroughly. A test with some hour and minute values would be better.

ggorlen
  • 44,755
  • 7
  • 76
  • 106