I need to create an array of elements in javascript, which add 2 hours to a certain time I set.
I give an example. The time is
14:00.
I need, to create an array that contains all 30 minute intervals up to 16:00.
Ex
14:00
14:30
15:00
15:30
Here is a function that produces the time specifications as strings. It can take an optional second argument to specify the end-time (16:00 in your question).
Two utility functions convert a time string to (and from) a number of minutes.
Finally, the result array is created with Array.from:
const toMinutes = str => str.split(":").reduce((h, m) => h * 60 + +m);
const toString = min => (Math.floor(min / 60) + ":" + (min % 60))
.replace(/\b\d\b/, "0$&");
function slots(startStr, endStr="16:00") {
let start = toMinutes(startStr);
let end = toMinutes(endStr);
return Array.from({length: Math.floor((end - start) / 30) + 1}, (_, i) =>
toString(start + i * 30)
);
}
console.log(slots("14:00"));
What I would do was to create two methods: addTime and createDateArray.
On addTime function we use to convert a timestamp into a Date object so it is easier for you to manage rather than an 14:00 string.
const addTime = (_dateTimestamp, addHours, addMinutes, addSeconds) => {
const date = new Date();
date.setTime( _dateTimestamp );
const newDate = new Date();
if(addHours) newDate.setHours( date.getHours() + addHours );
if(addMinutes) newDate.setMinutes( date.getMinutes() + addMinutes );
if(addSeconds) newDate.setSeconds( date.getSeconds() + addSeconds );
return newDate;
}
const createDateArray = (date, minuteInterval, amount) => {
let array = [];
for(let i = 1; i <= amount; i++) {
const time = addTime( date, 0, minuteInterval * i, 0);
array.push( time );
}
return array;
}
const dateToIncrement = new Date().getTime();
const minutesInterval = 30; // every 30 minutes
const amountTimes = 10; // will run through 10 times, so it'll calculate the minutes 10 times
const result = createDateArray( dateToIncrement, minutesInterval, amountTimes );
console.log(result);
You can also use the addTime function for other properties like hours and seconds if you wish by setting the second and last argument of the method.
I hope the code above makes sense and you can make use of it.
Here is function that generates time slots in specified boundaries, it's similar to trincot's answer, but doesn't use regex and works for the edge cases:
const timeStringToMinutes = (timeStr, separator) => timeStr.split(separator).reduce((h, m) => h * 60 + +m);
const minutesToTimeString = (minutes, separator) => {
const minutesPart = (minutes % 60).toString().padStart(2, "0");
const hoursPart = Math.floor(minutes / 60).toString().padStart(2, "0");
return hoursPart + separator + minutesPart;
}
function generateTimeSlots(startStr, endStr, periodInMinutes, separator = ":") {
let startMinutes = timeStringToMinutes(startStr, separator);
let endMinutes = timeStringToMinutes(endStr, separator);
const oneDayInMinutes = 1440;
if (endMinutes >= oneDayInMinutes)
endMinutes = oneDayInMinutes - 1;
if (startMinutes <= 0)
startMinutes = 0;
return Array.from({ length: Math.floor((endMinutes - startMinutes) / periodInMinutes) + 1 }, (_, i) =>
minutesToTimeString(startMinutes + i * periodInMinutes, separator)
);
}
console.log(generateTimeSlots("14:00", "15:30", 30));
You can create a basic function like this :
function getTimes(start) {
start = parseInt(start) * 2 + (+start.slice(-2) > 0);
end = start+60/12;
return Array.from({length: end - start}, (_, i) =>
(((i + start) >> 1) + ":" + ((i + start)%2*3) + "0").replace(/^\d:/, "0$&"));
};
And use with :
getTimes("14:00");
Related
const createTimeSlots=(fromTime,toTime)=>{
I want to add 15 minutes slot to each StartTime in a loop and store in array of objects.
Assuming the inputs are in timestamp, add 15 mins equivalent of timestamps and push that timestamp(or push mins/hrs etc.). Here's the code example where start time is current timestamp and endtime is current + 3hrs in timestamp.
function createSlots(start, end) {
let slots = [];
const mins = 15 * 60 * 1000; // 15 mins
const date = (dt) => new Date(dt);
while (start <= end) {
start += mins;
// only mins
//slots.push(date(start).getMinutes());
// hrs + mins
slots.push(`${date(start).getHours()}:${date(start).getMinutes()}`);
}
return slots;
}
var slots = createSlots(Date.now(), Date.now() + 3 * 3600 * 1000); // from (now) to (now + 3hrs)
console.log("slots : ", slots);
Let's assume inputs are valid date-time format.
This solution will work across dates, let's say you give the start time today and end time tomorrow then also it will work without any issue.
const createTimeSlots = (fromTime, toTime, slotLength =15*60) => {
let slotStart = new Date(fromTime).valueOf();
let slotEnd = new Date(fromTime).valueOf() + slotLength * 1000;
let endEpoch = new Date(toTime).valueOf();
let ob = [];
for (slotEnd; slotEnd <= endEpoch; slotEnd = slotEnd + slotLength * 1000) {
ob.push({
'from': formatDate(slotStart),
'to': formatDate(slotEnd)
});
slotStart = slotEnd;
}
return ob;
}
function formatDate(epoch) {
let d = new Date(epoch);
let month = String((d.getMonth() + 1)).padStart(2, '0');
let day = String((d.getDate())).padStart(2, '0');
let hours = String((d.getHours())).padStart(2, '0');
let mins = String((d.getMinutes())).padStart(2, '0');
return `${d.getFullYear()}-${month}-${day} ${hours}:${mins}`;
}
const from = "2022-05-25 23:00";
const to = "2022-05-26 01:00";
const slotLength = 15 * 60; //seconds
var r = createTimeSlots(from, to, slotLength );
console.log(r);
i get this time from an external JSON :
"time":"19:45"
I need to add 2 hours from this string.
Is it possible in JS?
Thanks
Try this
let myTime = '19:45'
function getTime(time, addHour) {
let [h, m] = time.split(':');
let date = new Date();
date.setHours(h, m, 0)
date.toString();
let res = `${date.getHours()+addHour}:${date.getMinutes()}`
return res
}
console.log(getTime( myTime, 2 ))
uses String.split to get hourNum and minuteNum, then construct one Date object and uses setTime to add two hours.
function addHours(text, hours=2) {
const [hourNum, minNum] = text.split(':')
const time = new Date(0, 0, 0, hourNum, minNum)
time.setTime(time.getTime() + (hours * 60 * 60 * 1000))
return `${time.getHours()}:${time.getMinutes()}`
}
console.log(addHours('19:45', 2))
console.log(addHours('23:45', 2))
A Date object isn't necessary to do time mathematics, it just means taking account of minutes and seconds (60) and maybe days (24).
E.g.
// Add time to a timestamp, both in in HH:mm format
// If respectDay is true, hours are % 24
function addTime(start, increment, respectDay = false) {
let pad = n => ('0' + n).slice(-2);
let timeToMins = time => time.split(':').reduce((h, m) => h*60 + m*1);
let minsToTime = (mins, respectDay = false) => `${pad((mins / 60 | 0) % (respectDay? 24 : Number.POSITIVE_INFINITY))}:${pad(mins%60)}`;
return minsToTime(timeToMins(start) + timeToMins(increment), respectDay);
}
let time = "19:45";
console.log(addTime(time, '8:23')); // Total time : 28:08
console.log(addTime(time, '8:23', true)); // As day time : 04:08
I'm adding two time strings in order to get single time string in h:m:s format with milliseconds to be added as well.
I only managed until the seconds. Now I also want to add the milliseconds
I also want to add more than two time strings, that is, more than two parameters
function addTimes (startTime, endTime) {
var times = [ 0, 0, 0 ]
var max = times.length
var a = (startTime || '').split(':')
var b = (endTime || '').split(':')
// normalize time values
for (var i = 0; i < max; i++) {
a[i] = isNaN(parseInt(a[i])) ? 0 : parseInt(a[i])
b[i] = isNaN(parseInt(b[i])) ? 0 : parseInt(b[i])
}
// store time values
for (var i = 0; i < max; i++) {
times[i] = a[i] + b[i]
}
var hours = times[0]
var minutes = times[1]
var seconds = times[2]
if (seconds >= 60) {
var m = (seconds / 60) << 0
minutes += m
seconds -= 60 * m
}
if (minutes >= 60) {
var h = (minutes / 60) << 0
hours += h
minutes -= 60 * h
}
return ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2) + ':' + ('0' + seconds).slice(-2)
}
alert(addTimes('9:10:10', '1:0:0'));
You can just extend your existing function to handle milliseconds the same way it's currently handling minutes and seconds, just with a factor of 1,000 instead of 60.
function addTimes(startTime, endTime) {
// Add element for milliseconds to times
var times = [0, 0, 0, 0];
var max = times.length;
// Split on ':' and '.'
var a = (startTime || '').split(/[:.]/);
var b = (endTime || '').split(/[:.]/);
// normalize time values
for (var i = 0; i < max; i++) {
a[i] = isNaN(parseInt(a[i])) ? 0 : parseInt(a[i]);
b[i] = isNaN(parseInt(b[i])) ? 0 : parseInt(b[i]);
}
// store time values
for (var i = 0; i < max; i++) {
times[i] = a[i] + b[i];
}
var hours = times[0];
var minutes = times[1];
var seconds = times[2];
// Add variable for milliseconds
var milliseconds = times[3];
// Add milliseconds first
if (milliseconds >= 1000) {
var s = (milliseconds / 1000) << 0;
seconds += s;
milliseconds -= 1000 * s;
}
// Continue as for original
if (seconds >= 60) {
var m = (seconds / 60) << 0;
minutes += m;
seconds -= 60 * m;
}
if (minutes >= 60) {
var h = (minutes / 60) << 0;
hours += h;
minutes -= 60 * h;
}
return ('0' + hours).slice(-2) + ':' +
('0' + minutes).slice(-2) + ':' +
('0' + seconds).slice(-2) + '.' +
// Add milliseconds to return
('00' + milliseconds).slice(-3);
}
console.log(addTimes('9:10:10.500', '1:0:55.501'));
I'd simplify things a bit and do away with the if statements and just do the overflow thing every time. Also, it can be made a bit more tolerant of partial strings and invalid values, e.g.
/* Add times in format h:mm:ss.sss
** return total time in same format
** Accepts partial times, first digit treated as hours
** e.g. 1:30 is equivalent to 1:30:00.000
** Invalid and missing parts treated as 0 (zero)
** #param {string} timeA : time in format h:mm:ss.sss
** #param {string} timeB : time in format h:mm:ss.sss
** #returns {string} sum of timeA and timeB in format h:mm:ss.sss
*/
function addTime(timeA, timeB) {
// Pad function for numbers less than 100
let z = (n, len) => String(n).padStart(len, '0');
// Split timestamps into parts as numbers, NaN => 0
let parts = s => String(s).split(/[:.]/).map(v => Number(v) || 0);
let [aH, aM, aS, aMs] = parts(timeA);
let [bH, bM, bS, bMs] = parts(timeB);
// Initialise total values, tx is just a placeholder
let tH = 0, tM = 0, tS = 0, tMs = 0, tX;
// Helper to add time values - omitting f just adds a + b
let factorSum = (a, b, f) => {
let t = (a || 0) + (b || 0);
return f? [t / f | 0, t % f] : [0, t];
};
// Add parts in order using helper
[tS, tMs] = factorSum(aMs, bMs, 1000);
[tM, tS] = factorSum(aS, bS + tS, 60);
[tH, tM] = factorSum(aM, bM + tM, 60);
[tX, tH] = factorSum(aH, bH + tH);
// Return formatted result
return tH + ':' + z(tM,2) + ':' + z(tS,2) + '.' + z(tMs,3);
}
// No overflow
console.log(addTime('1:01:01.001', '2:02:02.200')); // 3:03:03.201
// Overflow mins, secs, milliseconds
console.log(addTime('1:59:59.999', '0:00:00.001')); // 2:00:00.000
// Partial times
console.log(addTime('1', '2:30:1')); // 3:30:01.000
// Missing parameter treated as 0
console.log(addTime()); // 0:00:00.000
console.log(addTime('1:15')); // 1:15:00.000
// Invalid parts treated as zero
console.log(addTime('1:15', 'foo')); // 1:15:00.000
console.log(addTime('1:15', '2:blah:23.001')); // 3:15:23.001
If I could use a addition assignment += with destructuring it could be simpler, but that's not possible yet. :-)
I don't find any docs about it on moment.js website.
I need to calculate difference from 2 duration time (not dates).
For example:
27:10 - 7:20 = 19:50
where 27 is hours (can be bigger than 24h of a day) and 10 is minutes.
I see moment.js can operatore only with dates?
You can use moment.duration()
var d1, d2, dDiff, diff;
d1 = moment.duration('7:20', 'HH:mm');
d2 = moment.duration('27:10', 'HH:mm');
dDiff = d2.subtract(d1);
diff = dDiff.get('days') + ':day(s) ' + dDiff.get('hours') + ':' + dDiff.get('minutes');
console.log(diff); // "0:day(s) 19:50"
more details: momentjs durations
function getTimeDifference(start, end) {
var s = start.split(':');
var e = end.split(':');
var d = (parseInt(s[0], 10) * 60 + parseInt(s[1], 10)) - (parseInt(e[0], 10) * 60 + parseInt(e[1], 10));
var res = parseInt((d / 60), 10).toString() + ':' + (d % 60).toString();
alert(res);
}
getTimeDifference('27:10' , '7:20');
May be helpful to you...
You can do it using pure maths
function f1(a, b) {
const [hoursA, minutesA] = a.split(':').map(v => parseInt(v, 10));
const [hoursB, minutesB] = b.split(':').map(v => parseInt(v, 10));
let minutesDiff = 60 * (hoursA - hoursB) + (minutesA - minutesB)
const hoursDiff = (minutesDiff - minutesDiff % 60) / 60;
minutesDiff = minutesDiff % 60;
return hoursDiff + ':' + minutesDiff.toString().padStart(2,'0');
}
console.log(f1('27:10','7:20'))
console.log(f1('248:10','7:05'))
or using the date object
function f2(a, b) {
const [hoursA, minutesA] = a.split(':').map(v => parseInt(v, 10));
const [hoursB, minutesB] = b.split(':').map(v => parseInt(v, 10));
const time = new Date(Date.UTC(1970));
time.setUTCHours(hoursA - hoursB, minutesA - minutesB);
return ((time - time % 86400000) / 3600000 + time.getUTCHours()) + ':' + time.getUTCMinutes().toString().padStart(2,'0');
}
console.log(f2('27:10','7:20'))
console.log(f2('248:10','7:05'))
This doesn't need a library, you just need to do some base60 arithmetic.
You simply convert both to minutes, do a subtraction and convert back to hours and minutes
//27:10 - 7:20 = 19:50
function calculateDifference(time1,time2){
var diffMins = toMinutes(time1)-toMinutes(time2);
return toHoursMinutes(diffMins);
}
function toMinutes(time){
var [hrs,mins] = time.split(':').map(x => parseInt(x,10));
return hrs*60 + mins;
}
function toHoursMinutes(mins)
{
return Math.floor(mins/60) + ":" + (mins%60).toString().padStart('0',2);
}
console.log(calculateDifference("27:10","7:20"));
Suppose, I've an array of different time string.
let a: any = ["7:20", "5:50", "6:30"];
I want to sum up these HH:mm time strings. I am building up an app using Ionic 4 (Angular). I have already used momentjs for these. But, unfortunately yet I can't find any solution.
Update:
Expected Result:
7:20 + 5:50 + 6:30 = 19:40 (HH:33)
You can treat time as moment durations that can be summed up:
const any = ['7:20', '7:52', '5:03', '1:01', '9:02', '6:00'];
const sum = any.reduce((acc, time) => acc.add(moment.duration(time)), moment.duration());
console.log([Math.floor(sum.asHours()), sum.minutes()].join(':'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js"></script>
You could use reduce method by passing a callback function.
let arr= ["7:20", "5:50", "6:30"];
toSeconds = (str) => {
str = str.split(':');
return (+str[0]) * 60 + (+str[1]);
}
toHHss = (seconds) => {
let minutes = parseInt(seconds/60);
seconds = seconds - minutes*60;
return minutes + ':' + seconds;
}
let result = arr.reduce((r,elem) => r + toSeconds(elem), 0);
console.log(toHHss(result));
A POJS solution can be very simple:
/* Add array of time strings in H:mm format
** #param {Array<string>} timeArray - Array of H:mm
** #returns {string} - sum of times in H:mm format
*/
function addTimes(timeArray) {
let mins = timeArray.reduce((acc, time) => {
let [h, m] = time.split(':');
acc += h*60 + m*1;
return acc;
}, 0);
return (mins/60|0) + ':' + ('0'+(mins%60)).slice(-2);
}
// Example
console.log(addTimes(["7:20", "5:03", "6:42"]));
Vanilla Javascript implementation:
const secondsToHm = s => ({
hours: ((s - s % 3600) / 3600) % 60,
minutes: ((s - s % 60) / 60) % 60,
})
let a = ["7:20", "5:50", "6:30"];
let total = 0;
for(let i = 0; i < a.length; i++){
const aSlice = a[i].split(':');
const aSeconds = (+aSlice[0]) * 60 * 60 + (+aSlice[1]) * 60;
total += aSeconds
}
console.log(`${secondsToHm(total).hours}:${secondsToHm(total).minutes}`);
You can use moment.duration() to get the number of milliseconds for each time string in the array, and add them.
a.reduce((acc, t) => acc.add(moment.duration(t)), moment.duration())