How to reduce time using Javascript? - javascript

How can I use reduce() to calculate the total of all times (in string format) in the following array?
time["00:30", "01:45", "02:33"]
times.reduce((time, nextTime) => time + nextTime, 0)
I was thinking I need to split(":"), parseInt() and some more calculations or is there an easier way to do this?

If you can use an open JavaScript library like moment.js, the following is simple and preserves your string formatted times.
Note that I'm passing in "00:00" as the default value to reduce() so that times are calculated from a zero baseline, which also follows the string formatting that we'll use for all other values in the array.
const times["00:30", "01:45", "02:33"]
const totalTime = times.reduce((time, nextTime) => {
return moment(time, "hh:mm")
.add(nextTime, "hh:mm")
.format("hh:mm");
}, "00:00");
console.log("total time -->", totalTime);
// total time --> "04:48"
If we added logging inside reduce() to view the accumulation of values:
"12:30"
"02:15"
"04:48"
"total time -->" "04:48"
Notice that the result after the first pass was "12:30". If all times in the array summed to less than one clock hour the end result may not be acceptable for your particular use case.

This worked for me, this function timer is taking 2 times hh:mm:ss and splits it, divides, and then adds them together and after, it formats it to hh:mm:ss again
function timer(tempo1, tempo2) {
var array1 = tempo1.split(":");
var tempo_seg1 =
parseInt(array1[0]) * 3600 + parseInt(array1[1]) * 60 + parseInt(array1[2]);
var array2 = tempo2.split(":");
var tempo_seg2 =
parseInt(array2[0]) * 3600 + parseInt(array2[1]) * 60 + parseInt(array2[2]);
var tempofinal = parseInt(tempo_seg1) + parseInt(tempo_seg2);
var hours = Math.floor(tempofinal / (60 * 60));
var divisorMinutes = tempofinal % (60 * 60);
var minutes = Math.floor(divisorMinutes / 60);
var divisorSeconds = divisorMinutes % 60;
var seconds = Math.ceil(divisorSeconds);
var counter = "";
if (hours < 10) {
counter = "0" + hours + ":";
} else {
counter = hours + ":";
}
if (minutes < 10) {
counter += "0" + minutes + ":";
} else {
counter += minutes + ":";
}
if (seconds < 10) {
counter += "0" + seconds;
} else {
counter += seconds;
}
return counter;
}
export default timer;
and on my React App I used this code to keep track of the times and add them calling the timer function
const updateTime = () => {
let times = [];
let times2 = [];
if (todos.length > 1) {
for (let i = 0; i < todos.length; i++) {
times.push(todos[i].time + ":00");
}
times2 = times[0];
for (let i = 1; i < times.length; i++) {
times2 = timer(times2, times[i]);
}
times2 = times2.substr(0, 5);
} else if (todos.length == 1) times2 = todos[0].time;
else times2 = "No tasks";
return times2;
};
I only wanted hh:mm but for the sake of future implementation of seconds if needed, I'm going to add ":00" (seconds) and then remove it again using
times2 = times2.substr(0, 5);

Related

Sum Hours:Minutes:Seconds in Java script

how can I sum hours:minutes:seconds in JavaScript.
I mean by
04:32:05
03:14:03
To get
07:46:08
Ive tried
var time1 = "01:00:01";
var time2 = "01:00:10";
var time3 = "01:54:00";
var time4 = "01:30:00";
var time5 = "01:00:00";
var time6 = "01:00:00";
var time7 = "01:00:00";
var hour=0;
var minute=0;
var second=0;
var splitTime1= time1.split(':');
var splitTime2= time2.split(':');
var splitTime3= time3.split(':');
var splitTime4= time4.split(':');
var splitTime5= time5.split(':');
var splitTime6= time6.split(':');
var splitTime7= time7.split(':');
hour = parseInt(splitTime1[0]) + parseInt(splitTime2[0]) + parseInt(splitTime3[0]) + parseInt(splitTime4[0]) + parseInt(splitTime5[0]) + parseInt(splitTime6[0]) + parseInt(splitTime7[0])
minute = parseInt(splitTime1[1]) + parseInt(splitTime2[1]) + parseInt(splitTime3[1]) + parseInt(splitTime4[1]) + parseInt(splitTime5[1]) + parseInt(splitTime6[1]) + parseInt(splitTime7[1])
hour = hour + minute/60;
minute = minute%60;
second = parseInt(splitTime1[2]) + parseInt(splitTime2[2]) + parseInt(splitTime3[2])
+ parseInt(splitTime4[2]) + parseInt(splitTime5[2]) + parseInt(splitTime6[2]) +
parseInt(splitTime7[2])
minute = minute + second/60;
second = second%60;
console.log(hour+ ":" + minute + ":"+ second)
The output I get is 8.4:24.183333333333334:11 instad of 08:24:11
any suggestions?
your making it very complex, you can reduce this by converting into Date objects and then add each date to get the sum of all dates
Understanding Date and Time in JavaScript
The problem with your code is you are including the decimal point
hour = hour + minute/60;
you need to floor it.
hour = hour + Math.floor(minute/60);
Now how to do it without a lot of repetitive code.
function toSeconds(s) {
const parts = s.split(':');
return +parts[0] * 3600 + +parts[1] * 60 + +parts[2];
}
function secondsToHHMMSS(secs) {
return Math.floor(secs / 3600).toString().padStart(2, '0') + ':' +
(Math.floor(secs / 60) % 60).toString().padStart(2, '0') + ':' +
(secs % 60).toString().padStart(2, '0');
}
const timestamps = ["01:00:01", "01:00:10", "01:54:00", "01:30:00", "01:00:00", "01:00:00", "01:00:00"];
const totalSeconds = timestamps.reduce(function(total, ts) {
return total + toSeconds(ts);
}, 0);
const result = secondsToHHMMSS(totalSeconds);
console.log(result);
If you want to sum of times then you should try this
var addTime = function (time1, time2) {
// convert to ms
var dateObject1 = new Date(time1).valueOf();
var dateObject2 = new Date(time2).valueOf();
return dateObject1 + dateObject2;
}
var time1 = new Date().setHours(4, 32, 5, 0);
var time2 = new Date().setHours(3, 14, 3, 0);
var sum = new Date(addTime(time1, time2));
var getFormatedTime = function (time) {
return time.getHours()+':'+time.getMinutes()+':'+time.getSeconds()
}
console.log(getFormatedTime(sum))
The first thing you should look into is using an Array, since you have a number of objects of the same kind.
You should ideally have something like,
const times = ["04:32:05", "03:14:03", ...]
Once you have that, this problem reduces to a classic use-case for the reduce function.
The reduce function operates on an array and accumulates the value of the operation every step to yield one value at the end.
Here's an example solution for your problem
const times = ["04:32:05", "03:14:03"]
//const times = ["01:00:01", "01:00:10","01:54:00","01:30:00"]
let finalSum = times.reduce((sum, curr) => {
//Obtain the current timestamp as an array of numbers
//[HRS, MINS, SECS]
let currTimeStamp = curr.split(":").map(token => parseInt(token));
//Add the current seconds to the total seconds so far
sum[2] += currTimeStamp[2];
//See how many minutes you got leftover as a result of that addition
const leftOverMins = Math.floor(sum[2] / 60);
//Mod by 60, to keep the seconds under 60
sum[2] %= 60;
//Add the leftover minutes to the sum operation for minutes
sum[1] += (currTimeStamp[1] + leftOverMins);
//Similar procedure as above
const leftOverHours = Math.floor(sum[1] / 60);
sum[1] %= 60;
sum[0] += (currTimeStamp[0] + leftOverHours);
sum[0] %= 24;
return sum
}, [0, 0, 0])
console.log(finalSum.join(":"))
Hello hope this answer will help you, I recommand to replace your bottom part (where you calculate) I do pretty much the same thing, but in the good order and with round to avoid decimals problems
var time1 = "01:00:01";
var time2 = "01:00:10";
var time3 = "01:54:00";
var time4 = "01:30:00";
var time5 = "01:00:00";
var time6 = "01:00:00";
var time7 = "01:00:00";
var hour=0;
var minute=0;
var second=0;
var splitTime1= time1.split(':');
var splitTime2= time2.split(':');
var splitTime3= time3.split(':');
var splitTime4= time4.split(':');
var splitTime5= time5.split(':');
var splitTime6= time6.split(':');
var splitTime7= time7.split(':');
var allTimes = [splitTime1, splitTime2, splitTime3, splitTime4, splitTime5, splitTime6, splitTime7]
allTimes.forEach(element => {
hour += parseInt(element[0])
minute += parseInt(element[1])
second += parseInt(element[2])
})
minute += Math.round(second / 60);
second = second % 60;
hour += Math.round(minute / 60);
minute = minute % 60
console.log(hour+ ":" + minute + ":"+ second)

Subtract time and show difference in mins:secs format

I want to accurately display the difference between two times. The different should be displayed in a format such as mm:ss
methods: {
calcuateTimeDifference: function (startTime, endTime) {
let result = 0;
if (startTime && endTime) {
let start = startTime.split(":");
let end = endTime.split(':');
let startTimeInHrs = (parseFloat(start[0]/3600) + parseFloat(start[1]/60) + parseFloat(start[2]/3600));
let endTimeInHrs = (parseFloat(end[0]/3600) + parseFloat(end[1]/60) + parseFloat(end[2] /3600));
result = endTimeInHrs - startTimeInHrs;
}
return result.toFixed(2);
},
Using this function - the difference between the following times: 16:03:01 - 16:04:01 - I get the result as -32.00.
split the strings on : to get the hours, minutes, and seconds
convert all to seconds and add them to get the total seconds from each time
subtract the two to get the difference in seconds
convert the difference seconds to hours, minutes and seconds using the modules operator(%)
format the result for appropriate display
let start = "16:03:01";
let end = "16:04:05";
let time = calcuateTimeDifference(start, end);
console.log(time);
function calcuateTimeDifference(startTime, endTime) {
let result = 0;
if (startTime && endTime) {
const start = startTime.split(':').map(Number);
const end = endTime.split(':').map(Number);
const startSeconds = (60*60) * start[0] + 60*start[1] + start[2];
const endSeconds = (60*60) * end[0] + 60*end[1] + end[2];
const diffSeconds = endSeconds - startSeconds;
seconds = parseInt((diffSeconds) % 60);
minutes = parseInt((diffSeconds/60) % 60);
hours = parseInt((diffSeconds/(60*60)) % 24);
//append `0` infront if a single digit
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return `${hours}:${minutes}:${seconds}`;
}
console.log("Invalid Input");
}
function calcuateTimeDifference(startTime, endTime) {
let toSeconds = (time) => {
let [h, m, s] = time.split(':');
return h * 360 + m * 60 + +s;
};
let d = Math.abs(toSeconds(startTime) - toSeconds(endTime));
let mm = String(Math.floor(d / 60));
if (mm.length == 1) mm = '0' + mm;
let ss = String(d % 60);
if (ss.length == 1) ss = '0' + ss;
return `${mm}:${ss}`;
}

Conversion of millisecond to hours format

I have a start date, time and end date, time and also i am finding out the total duration of travel. The output is in millisecond and i need to convert this into hours format. By searching other answers here i tried the following but no result.
<md-cell *mdCellDef="let row"> {{row?.duration | formatDuration}} </md-cell>
And ts file:
export class StoppageComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
filter('formatDuration', function () {
return function (input) {
var totalHours, totalMinutes, totalSeconds, hours, minutes, seconds, result='';
totalSeconds = input / 1000;
totalMinutes = totalSeconds / 60;
totalHours = totalMinutes / 60;
seconds = Math.floor(totalSeconds) % 60;
minutes = Math.floor(totalMinutes) % 60;
hours = Math.floor(totalHours) % 60;
if (hours !== 0) {
result += hours+':';
if (minutes.toString().length == 1) {
minutes = '0'+minutes;
}
}
result += minutes+':';
if (seconds.toString().length == 1) {
seconds = '0'+seconds;
}
result += seconds;
return result;
};
});
}
I think the error is with ts file, as i am new in angular.
Is there is any direct conversion using pipe without using functions?
Other answers looks complicated, finally found out a solution myself..
Html as,
<md-cell *mdCellDef="let row"> {{getFormathours(row?.duration)}} </md-cell>
And ts,
getFormathours(input) {
var totalHours, totalMinutes, totalSeconds, hours, minutes, seconds, result='';
totalSeconds = input / 1000;
totalMinutes = totalSeconds / 60;
totalHours = totalMinutes / 60;
seconds = Math.floor(totalSeconds) % 60;
minutes = Math.floor(totalMinutes) % 60;
hours = Math.floor(totalHours) % 60;
console.log (hours + ' : ' + minutes + ' : ' + seconds);
if (hours !== 0) {
result += hours+' hr:';
if (minutes.toString().length == 1) {
minutes = '0'+minutes;
}
}
result += minutes+' min';
if (seconds.toString().length == 1) {
seconds = '0'+seconds;
}
result += seconds;
return result;
}
This gives the exact output that i needed and much more clear solution based on my question.. Anyhow i appreciate others answers too for your effort.
You do not need to reinvent the wheel. You can use Date objects to get duration.
Assuming you have 2 date objects,
Get the difference between them. Since you already have millseconds, you already have completed this step.
Now create a new date object and remove time value.
Now when you set new time value(difference) to it, you have all the values. Just use the function and get the values and display in your format.
function getTravelDuration(date1, date2) {
var diff = +date2 - +date1;
var today = new Date();
today.setHours(0,0,0,0);
var arrival = new Date(+today + diff);
var duration = ['getFullYear', 'getMonth', 'getDate', 'getHours', 'getMinutes', 'getSeconds'].reduce(function(p,c,i,a){
var value = arrival[c]() - today[c]();
if(value) {
p += value;
p += ((c === 'getFullYear') ? ' Year' : c.replace('get', ' ')) + ' '
}
return p;
}, '');
console.log(duration);
}
function doubleDigits(str){
return ('00' + str).slice(-2)
}
getTravelDuration(new Date(2017, 10, 5, 5), new Date(2017, 10, 5, 15, 23));
getTravelDuration(new Date(2017, 10, 5, 5), new Date(2017, 10, 6, 15, 23, 30));
For me, the best choice (without errors) is use the moment library, instead Date.
Please check https://momentjs.com/docs/
var t1 = moment('2017/10/5 15:23');
var t2 = moment('2017/10/5 15:23');
var differenceMinutes = t1.diff(t2, 'minutes');
var differenceMilliseconds = t1.diff(t2, 'minutes');
Using popular and tested libraries, could be better. You can use in angular templates:
https://github.com/urish/angular2-moment
Example:
{{startDate | amDifference: endDate :'' }}
you can use this code directly
export class StoppageComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
filter('formatDuration', function () {
return function (input) {
var result = new Date(input);
var n = (d.getDate().toString()) +'/'+ (d.getMonth().toString())+'/' +(d.getFullYear().toString()) + ' '+ (d.getHours().toString()) +':'+ (d.getHours().toString()) +':'+ (d.getSeconds().toString());
return result;
};
});
}

JS/TypeScript Generate times between hours

So let's say we have two times:
7:30 - 12:00
So my question is how can I generate an array with times like this:
7:30, 8:00, 8:30, 9:00, 9:30, 10:00, 10:30, 11:00, 11:30
I need this for a booking, so let's say the business will open at 7:30 and every booking that you can make will be 30 min(this time can change, could be one hour or more)
Whats the best way to generate something like this in JS?
Little verbose utility, you can use it..
var getTimeIntervals = function (time1, time2, slotInMinutes, workingHourStart, workingHourEnd) {
time1.setMinutes(0); time1.setSeconds(0);
var arr = [];
var workingHoursStart = workingHourStart;
var workingHourEnds = workingHourEnd;
var workingHourStartFloat = parseFloat("7:30");
var workingHourEndFloat = parseFloat("12:00");
while(time1 < time2){
var generatedSlot = time1.toTimeString().substring(0,5);
var generatedSlotFloat = parseFloat(generatedSlot);
time1.setMinutes(time1.getMinutes() + slotInMinutes);
if(generatedSlotFloat >= workingHourStartFloat && generatedSlotFloat < workingHourEndFloat){
var generatedObject = {
slot: time1.toTimeString().substring(0,5),
timeStamp: new Date(time1.getTime())
};
arr.push(generatedObject);
}
}
return arr;
}
var today = new Date();
var tomrorow = new Date().setDate(today.getDate()+1);
console.log(getTimeIntervals(today, tomorrow, 30, "7:30", "12:00"));
Function getTimeIntervals expects startDate, endDate, slotDurationInMinutes, workingHoursStart and workingHourEnd.
Why I am returning object is because you may need the timestamp of selected slot in your further application use.
Fiddle - https://jsfiddle.net/rahulrulez/t8ezfj2q/
As the comment in the code says, you can remove the 0 before the hours if you don't want it, by removing that line.
If you don't want the end in the array just replace the <= by <in the for loop
function timeArray(start, end){
var start = start.split(":");
var end = end.split(":");
start = parseInt(start[0]) * 60 + parseInt(start[1]);
end = parseInt(end[0]) * 60 + parseInt(end[1]);
var result = [];
for ( time = start; time <= end; time+=30){
result.push( timeString(time));
}
return result;
}
function timeString(time){
var hours = Math.floor(time / 60);
var minutes = time % 60;
if (hours < 10) hours = "0" + hours; //optional
if (minutes < 10) minutes = "0" + minutes;
return hours + ":" + minutes;
}
console.log(timeArray("7:30", "12:00"));
A shorter version:
timeArray = [];
....
let i = 0;
let hour = 8;
let odd: boolean;
do {
odd = false;
if (i % 2 === 0) {
odd = true;
hour--;
}
this.timeArray.push(hour.toString() + (odd ? ":30" : ":00"));
i++;
hour++;
} while (i < 12);
....
Demo

Convert from seconds to specific format of minutes - Javascript

For example:
I have 101.2914
and I want to obtain
1:41.291
I thought to substract the integer part of the number minus 60, but I can't because could be that final time would be 2:XX.XXX
ES6:
const string = '101.2914';
let [sec, milisec] = string.split('.');
sec = +sec;
milisec = milisec.slice(0, 3);
let mins = 0;
while(sec >= 60) {
mins += 1;
sec -= 60;
}
const result = `${mins}:${sec}.${milisec}`;
console.log(result);
Old version:
var string = '101.2914';
var array = string.split('.');
var sec = +array[0];
var milisec = array[1].slice(0, 3);
var mins = 0;
while(sec >= 60) {
mins += 1;
sec -= 60;
}
var result = mins + ':' + sec + '.' + milisec;
console.log(result);
Yo Can use a function like this as well. Here i am setting input inside the function but you can pass it while calling function.
$scope.secToMinute= function (input) {
input = 101.2914;
var min = Math.floor(input/ 60);
var second = input - (min * 60);
alert(min + ":" + second.toFixed(3));
};
I hope this may help you.
var seconds = '101.2914';
var date = new Date(0,0,0);
date.setSeconds(seconds);
var result = date.getMinutes() +':'+date.getSeconds()+'.'+seconds.split('.')[1].slice(0,3);

Categories

Resources