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
Related
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);
I have two time values that should subtract and output the difference in hours. For example I get the values in this format:
0530-2400
That value is a string. I guess that converting to JavaScript Date object is the first step. Here is what I have so far:
var time = "0530-2400",
arr = [];
arr = time.split('-');
var dateObj = new Date(),
hours1 = dateObj.setHours(Number(arr[0].substring(0, 2))),
hours2 = dateObj.setHours(Number(arr[1].substring(0, 2))),
minutes1 = dateObj.setMinutes(Number(arr[0].substring(2, 4))),
minutes2 = dateObj.setMinutes(Number(arr[1].substring(2, 4)));
console.log(hours1);
console.log(minutes1);
console.log(hours2);
console.log(minutes2);
The output for the time I showed above should be 18.5 hours. If we subtract 24-5.5(530) = 18.5
The increments are always on 15,30 or 45 minutes. Is there a good way to convert string and then do the math in JS?
If there cannot be hours spanning multiple days, you can do it using simple math:
var time = "0530-2400",
difference = calcDifference(time);
console.log(difference);
function calcDifference(time) {
var arr = time.split('-').map(function(str) {
var hours = parseInt(str.substr(0, 2), 10),
minutes = parseInt(str.substr(2, 4), 10);
return (hours * 60 + minutes) / 60;
});
return arr[1] - arr[0];
}
Here you go:
var time = "0530-2400",
arr = [];
arr = time.split('-');
var date1 = new Date(), date2 = new Date();
date1.setHours(Number(arr[0].substring(0, 2)));
date2.setHours(Number(arr[1].substring(0, 2)));
date1.setMinutes(Number(arr[0].substring(2, 4)));
date2.setMinutes(Number(arr[1].substring(2, 4)));
var msInAHour = 1000*60*60;
var msDiff = date2 - date1;
var diffInHours = msDiff/msInAHour;
console.log(diffInHours.toFixed(1));
Hint: It's a lot easier to work with dates if you use Moment.js.
Here: https://momentjs.com/
Here's a more advanced version of the code:
var dt = "0530-2400".split('-')
.map(e=>new Date('1980-01-01'+e.replace(/(\d{2})(\d{2})/," $1:$2")));
var diffInHours = ((dt[1]-dt[0])/(3600000)).toFixed(1);
console.log(diffInHours);
var totalmin = 18.5*60
var min = total % 60;
var hours = (totalmin - min)/ 60;
min: 30, hours: 18
If you want to convert military hours to standard:
if (hours > 0 && hours <= 12) {
var standardHours= "" + hours;
} else if (hours > 12) {
var standardHours= "" + (hours - 12);
} else if (hours == 0) {
var standardHours= "12";
}
standardHours: 6
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;
};
});
}
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:
new Date(new Date(0, 0, 0, 00, 00, 00, 0)).setMinutes(30)
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.
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"
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);
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.
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)
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);
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'
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
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}`;
}
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.
I am getting the time duration correctly for 24 hrs format but for 12 hrs format I am getting error if i give 11:00 am to 1:00 pm. If I give 10:00 am to 11:00 am it will correctl and if I give 6:00 pm to 7:00 pm it will give correctly only in am to pm i m facing problem.
function autoChangeDuration() {
var diff1 = "00:00";
var start = document.getElementById("startTime").value;
var end = document.getElementById("endTime").value;
if (start > end) {
document.getElementById("duration").value = diff1;
} else {
var space1 = start.split(' ');
var space2 = end.split(' ');
s = space1[0].split(':');
e = space2[0].split(':');
var diff;
min = e[1] - s[1];
hour_carry = 0;
if (min < 0) {
min += 60;
hour_carry += 1;
}
hour = e[0] - s[0] - hour_carry;
diff = hour + ":" + min;
document.getElementById("duration").value = diff;
}
function toDate(s) {
// the date doesn't matter, as long as they're the same, since we'll
// just use them to compare. passing "10:20 pm" will yield 22:20.
return new Date("2010/01/01 " + s);
}
function toTimeString(diffInMs) {
// Math.max makes sure that you'll get '00:00' if start > end.
var diffInMinutes = Math.max(0, Math.floor(diffInMs / 1000 / 60));
var diffInHours = Math.max(0, Math.floor(diffInMinutes / 60));
diffInMinutes = diffInMinutes % 60;
return [
('0'+diffInHours).slice(-2),
('0'+diffInMinutes).slice(-2)
].join(':');
}
function autoChangeDuration()
{
var start = document.getElementById("startTime").value;
var end = document.getElementById("endTime").value;
start = toDate(start);
end = toDate(end);
var diff = (end - start);
document.getElementById("duration").value = toTimeString(diff);
}
Why don't you just use javascript's Date class?
http://www.w3schools.com/jsref/jsref_obj_date.asp