I have an HTML Table used to generate a Calendar which shows TimeClock entries for each day a user has worked and clocked in and out of the system. Each day also shows the total time duration for each clock in/out entry. (multiple "timecard punches" can be within the same day)
Simply put I have DateTime style strings which hold a Duration value and I need to add them all together to get a combined duration value.
In a loop this JavaScript variable totalTimeValue
will be assigned a duration value as a text string like this 03:31:23
Add these duration strings together using JavaScript...
03:31:23
04:21:56
04:08:42
03:31:17
04:10:59
02:48:21
04:26:11
00:00:39
03:41:37
Using JavaScript and jQuery I have this code below which gets the DateTime Duration value as a string in the format 04:21:19 for each timeclock entry.
My JavaScript/jQuery so far...
Demo of it working here: http://codepen.io/jasondavis/pen/GpPPPR?editors=101
var totalTimeValue = 0;
var totalWeekTimeValue = 0;
// itterate each week which is table row <tr>
$('#timeclock-cal > tbody > tr').each(function() {
console.log('=== New Week ===');
totalWeekTimeValue = 0;
// get each day which is a table cell <td>
$(this).find('td').each(function() {
console.log('== New Day ==');
// get total time val for each clock in/out on each day which is inside
// button with CSS class .cal-punch-total-time
$(this).find('.cal-punch-total-time').each(function() {
totalTimeValue = $(this).text();
console.log(totalTimeValue);
// THIS PART NEEDS YOUR HELP!
// NEED TO ADD EACH DATETIME STRING TOGETHER FOR TOTAL DURATION VALUES
totalWeekTimeValue = totalTimeValue+totalWeekTimeValue;
});
});
console.log('= total week time === '+totalWeekTimeValue);
});
full size image
I have no objection to using the MomentJS library http://momentjs.com/ if it can help in this situation however my research so far did not really show any examples doing what I need to do in this question.
In fact all my StackOverflow and Google searches resulted in no examples of adding durations like this in JavaScript!
I did find this MomentJS plugin MomentJS Durations - https://github.com/jsmreese/moment-duration-format
With JQuery and Javascript its easily possible. Please have a look at below code.
$(document).ready(function(){
var pad = function(num) { return ("0"+num).slice(-2); }
var totalSeconds = 0;
$("li").each(function(){
var currentDuration = $(this).text();
currentDuration = currentDuration.split(":");
var hrs = parseInt(currentDuration[0],10);
var min = parseInt(currentDuration[1],10);
var sec = parseInt(currentDuration[2],10);
var currDurationSec = sec + (60*min) + (60*60*hrs);
totalSeconds +=currDurationSec;
});
var hours = Math.floor(totalSeconds / 3600);
totalSeconds %= 3600;
var minutes = Math.floor(totalSeconds / 60);
var seconds = totalSeconds % 60;
$(".totalVal").text(pad(hours)+":"+pad(minutes)+":"+pad(seconds));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
<li>03:31:23</li>
<li>04:21:56</li>
<li>04:08:42</li>
<li>03:31:17</li>
<li>04:10:59</li>
<li>02:48:21</li>
<li>04:26:11</li>
<li>00:00:39</li>
<li>03:41:37</li>
</ul>
<div id="totalTime">Total Time:<span class="totalVal"></span></div>
This is a little overkill, but shows how to use map and reduce.
/** Calculate the number of seconds from HH:MM:SS **/
function getSeconds(time) {
var parts = time.split(":");
return parseInt(parts[0], 10) * 3600 + parseInt(parts[1], 10) * 60 + parseInt(parts[2], 10);
}
//select all the elements
var totalSeconds = $("a.cal-punch-total-time")
.map( function(ind, elem) { //convert the jQuery object into the array
var text = $(elem).text(); //get the text from the anchor
return getSeconds(text); //set the index to the total seconds
})
.get() //gets the array out of the jQuery object
.reduce( function(runningTotal, currentValue){ //Now to combine all the values into one
return runningTotal + currentValue; //sum up the values
},0); //The initial starting vaule
//Now get the hour, minutes, and seconds from the total seconds
var hours = parseInt( totalSeconds / 3600 );
var minutes = parseInt( totalSeconds / 60 ) % 60;
var seconds = totalSeconds % 60;
//left pad numbers less than ten
if(hours<10) hours = "0" + hours;
if(minutes<10) minutes = "0" + minutes;
if(seconds<10) seconds = "0" + seconds;
$("#out").html("Total Time: " + (hours + ":" + minutes + ":" + seconds));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a class="cal-punch-total-time">03:31:23</a>
<a class="cal-punch-total-time">04:21:56</a>
<a class="cal-punch-total-time">04:08:42</a>
<a class="cal-punch-total-time">03:31:17</a>
<a class="cal-punch-total-time">04:10:59</a>
<a class="cal-punch-total-time">02:48:21</a>
<a class="cal-punch-total-time">04:26:11</a>
<a class="cal-punch-total-time">00:00:39</a>
<a class="cal-punch-total-time">03:41:37</a>
<div id="out"></div>
You can split your DateTime strings into arrays.
totalTimeValue = $(this).text().split(':'); //from '03:10:30' to ['03','10','30']
Then loop through your array and coerce each string to a number.
totalTimeValue.forEach(function(val,idx){
totalWeekTimeValue[idx] += Number(val);
});
This will leave you with an array of values for totalWeekTime that you can format/recalculate and rejoin if needed.
totalWeekTimeValue.join(':'); //[3:10:30]
http://codepen.io/hirechrismeyers/pen/ZbVVgr
Try this:
function hhmmssToSeconds(str) {
var arr = str.split(':').map(Number);
return (arr[0] * 3600) + (arr[1] * 60) + arr[2];
};
function secondsToHHMMSS(seconds) {
var hours = parseInt(seconds / 3600, 10),
minutes = parseInt((seconds / 60) % 60, 10),
seconds = parseInt(seconds % 3600 % 60, 10);
return [hours, minutes, seconds].map(function (i) { return i.toString().length === 2 ? i : '0' + i; }).join(':');
}
Then:
var t1 = hhmmssToSeconds('40:50:40'),
t2 = hhmmssToSeconds('04:12:30');
var result = secondsToHHMMSS(t1 + t2); // '45:03:10'