I have a cron job running on the server that performs some action every 6 hours UTC.
On the client page, I want to show a countdown that shows the time remaining for the next cron job to run.
If it was running at midnight I could have done
function timeToMidnight() {
var now = new Date();
var end = moment().endOf("day");
return end - now + 1000;
}
But I am not able to figure out how to do this for 6 hourly UTC (1200 AM, 0600 AM, 1200 PM, 0600 AM)
You can calculate it quite easily without moment
const timeToNextRun = (start) => {
const sixHoursInMs = 6 * 3600 * 1000;
let remainingTime = sixHoursInMs - (start.getTime() % sixHoursInMs);
return remainingTime;
};
let now = new Date();
let countdown = timeToNextRun(now);
console.log(`Setting timer for ${countdown}ms - ${new Date(now.getTime() + countdown).toISOString()}`);
Just count down to any of these
const getDates = () => {
const d = new Date()
const utcDate = new Date(Date.UTC(d.getFullYear(),d.getMonth(), d.getDate(),6,0,0))
return [utcDate,new Date(utcDate.getTime() + (21600000)),new Date(utcDate.getTime() + (21600000*2)),new Date(utcDate.getTime() + (21600000*3))]
}
console.log(getDates())
Related
I am working on a project that requires a time in the future to be set using the Date object.
For example:
futureTime = new Date();
futureTime.setHours(futureTime.getHours()+2);
My questions is; once the future date is set, how can I round to the closest full hour and then set the futureTime var with it?
For example:
Given 8:55 => var futureTime = 9:00
Given 16:23 => var futureTime = 16:00
Any help would be appreciated!
Round the minutes and then clear the minutes:
var date = new Date(2011,1,1,4,55); // 4:55
roundMinutes(date); // 5:00
function roundMinutes(date) {
date.setHours(date.getHours() + Math.round(date.getMinutes()/60));
date.setMinutes(0, 0, 0); // Resets also seconds and milliseconds
return date;
}
The other answers ignore seconds and milliseconds components of the date.
The accepted answer has been updated to handle milliseconds, but it still does not handle daylight savings time properly.
I would do something like this:
function roundToHour(date) {
p = 60 * 60 * 1000; // milliseconds in an hour
return new Date(Math.round(date.getTime() / p ) * p);
}
var date = new Date(2011,1,1,4,55); // 4:55
roundToHour(date); // 5:00
date = new Date(2011,1,1,4,25); // 4:25
roundToHour(date); // 4:00
A slightly simpler way :
var d = new Date();
d.setMinutes (d.getMinutes() + 30);
d.setMinutes (0);
Another solution, which is no where near as graceful as IAbstractDownvoteFactory's
var d = new Date();
if(d.getMinutes() >= 30) {
d.setHours(d.getHours() + 1);
}
d.setMinutes(0);
Or you could mix the two for optimal size.
http://jsfiddle.net/HkEZ7/
function roundMinutes(date) {
return date.getMinutes() >= 30 ? date.getHours() + 1 : date.getHours();
}
As a matter of fact Javascript does this default which gives wrong time.
let dateutc="2022-02-17T07:20:00.000Z";
let bd = new Date(dateutc);
console.log(bd.getHours()); // gives me 8!!!!!
it is even wrong for my local time because I am GMT+2 so it should say 9.
moment.js also does it wrong so you need to be VERY carefull
Pass any cycle you want in milliseconds to get next cycle example 1 hours
function calculateNextCycle(interval) {
const timeStampCurrentOrOldDate = Date.now();
const timeStampStartOfDay = new Date().setHours(0, 0, 0, 0);
const timeDiff = timeStampCurrentOrOldDate - timeStampStartOfDay;
const mod = Math.ceil(timeDiff / interval);
return new Date(timeStampStartOfDay + (mod * interval));
}
console.log(calculateNextCycle(1 * 60 * 60 * 1000)); // 1 hours in milliseconds
I'm trying to get times of available slots. I have startDateTime, endDateTime, duration, and bufferBetweenSlots fields in my db. with some calculations I have figured out number of available slots.
the value of fields are:
startDateTime: 8/20/2021 11:30 AM
endDateTime: 8/20/2021 9:30 PM
duration: 60
bufferBetweenSlots: 30
but I'm not sure how to get the start and end time for the available slots. e.g. 10:00 - 11:00
const getTimeDiffInMins = (endTime, startTime) =>
(+new Date(endTime) - +new Date(startTime)) / (60 * 1000);
const getMultipleTimeSlots = (data) => {
const diff = getTimeDiffInMins(data.end_date_time, data.start_date_time);
const totalSlots = diff / data.duration;
const totalBuffer = data.buffer_between_slots * totalSlots;
const availableSlots = (diff - totalBuffer) / 60;
return availableSlots;
};
any suggestions?
You should only need a buffer between slots, so the number of buffers is one less than the number of slots, i.e. you want to solve:
n * slotTime + (n - 1) * bufferTime == totalTime
such that:
totalTime <= diff
You can do that by adding the buffer to totalTime and dividing by slotTime + bufferTime, then flooring the result to get the whole number of available slots plus buffers. Then you can just iterate to produce the required start and end time. E.g.
let startDateTime = new Date(2021,7,8,11,30); // 20 Aug 2021 11:30
let endDateTime = new Date(2021,7,8,22); // 20 Aug 2021 22:00
let duration = 60; // minutes
let bufferBetweenSlots = 30; // minutes
let diff = (endDateTime - startDateTime) / 6e4; // minutes
let numberOfSlots = Math.floor((diff + bufferBetweenSlots) / (duration + bufferBetweenSlots)); // minutes
let slots = [];
let time = new Date(startDateTime);
for (let i = 0; i < numberOfSlots; i++) {
// Add the slot start time
slots[i] = {start: time.toString()};
// Increment time to end of slot
time.setMinutes(time.getMinutes() + duration);
// Add the end time
slots[i].end = time.toString();
// Increment time to end of buffer
time.setMinutes(time.getMinutes() + bufferBetweenSlots);
}
console.log(slots);
I changed the end time to 22:00 to show it only puts in full slots. Whether you push timestamps or Date objects into the slots array is up to you. Just remember, if adding dates, to copy the date like:
slots[i] = {start: new Date(+time)};
...
slots[i].end = new Date(+time);
Thanks #RobG for taking the time to answer. here's how I managed to slove it.
const getTimeDiffInMins = (endTime, startTime) =>
(+new Date(endTime) - +new Date(startTime)) / (60 * 1000);
const convertToMilliSecs = (value) => value * 60 * 1000;
// coming from the db
const data = {
duration: 60,
buffer_between_slots: 30,
start_date_time: '2021-08-20T10:30:00Z',
end_date_time: '2021-08-20T20:30:00Z',
};
const {
duration: a,
buffer_between_slots: b,
end_date_time: x,
start_date_time: y,
} = data;
const duration = getTimeDiffInMins(x, y);
const slotDuration = a;
const totalSlots = a + b;
const numberOfSlots = Math.floor(duration / totalSlots);
const slotsAvailable = [...Array(numberOfSlots).keys()].map((slotNumber) => {
const slotStart = (slotNumber - 1) * totalSlots;
const slotEnd = slotStart + slotDuration;
return {
start: +new Date(y) + convertToMilliSecs(slotStart),
end: +new Date(y) + convertToMilliSecs(slotEnd),
};
});
/*
Now we can format the time however we want
I'm using momentjs:
moment(new Date(slot.start)).format('h:mma')
*/
console.log(slotsAvailable);
I am creating a countdown website. I want it to count down from the current time the my celebration date 2019-11-29 00:00:00. I want the timezone to be in Australia Brisbane time zone. However, it seems to be that it keeps calculating the amount of time left till my celebration date wrong. Could someone tell me what I did wrong? And once the time hits 0, how can I get rid of the countdown and replace it with Its celebration time
function dateDiff(a, b) {
// Some utility functions:
const getSecs = dt => (dt.getHours() * 24 + dt.getMinutes()) * 60 + dt.getSeconds();
const getMonths = dt => dt.getFullYear() * 12 + dt.getMonth();
// 0. Convert to new date objects to avoid side effects
a = new Date(a);
b = new Date(b);
if (a > b) [a, b] = [b, a]; // Swap into order
// 1. Get difference in number of seconds during the day:
let diff = getSecs(b) - getSecs(a);
if (diff < 0) {
b.setDate(b.getDate()-1); // go back one day
diff += 24*60*60; // compensate with the equivalent of one day
}
// 2. Get difference in number of days of the month
let days = b.getDate() - a.getDate();
if (days < 0) {
b.setDate(0); // go back to (last day of) previous month
days += b.getDate(); // compensate with the equivalent of one month
}
// 3. Get difference in number of months
const months = getMonths(b) - getMonths(a);
return {
years: Math.floor(months/12),
months: months % 12,
days,
hours: Math.floor(diff/3600),
minutes: Math.floor(diff/60) % 24,
seconds: diff % 60
};
}
// Date to start on
var celebrationDate = new Date("2019-11-29 00:00:00").toLocaleString("en-US", {timeZone: "Australia/Brisbane"});
// Update the count every 1 second
!function refresh () {
const diff = dateDiff(new Date().toLocaleString("en-US", {timeZone: "Australia/Brisbane"}), celebrationDate);
document.getElementById("day-val").innerHTML = diff[Object.keys(diff)[2]];
document.getElementById("hour-val").innerHTML = diff[Object.keys(diff)[3]];
document.getElementById("min-val").innerHTML = diff[Object.keys(diff)[4]];
document.getElementById("sec-val").innerHTML = diff[Object.keys(diff)[5]];
setTimeout(refresh, 1000)
}()
<div id="day-val"></div><div>Days</div><br>
<div id="hour-val"></div><div>Hours</div><br>
<div id="min-val"></div><div>Minutes</div><br>
<div id="sec-val"></div><div>Seconds</div>
IF you are using moment.js
What you can do is use the diff and duration functions like so:
const now = moment();
const celebrationDate= moment("2019-11-30 00:00:00");
// this will get the difference between now and celebrationDate
const celebrationDateDiff = expiration.diff(now);
// convert it into duration
const duration = moment.duration(celebrationDateDiff);
You can then access the countdown like:
duration.days() // will return the number of days
duration.hours() // will return the number of remaining hours
duration.minutes() // will return the number of remaining minutes
Solution with plain javascript:
Get the clients time zone offset
Calculate the diff between client offset and "Australian/Brisbane" offset
Calculate time left by targetDate - currentDate - offsetDiff
Format the result to display it
Example:
const minToMS = min => min * 60 * 1000
const getCountDownFromMS = diff => {
const milliseconds = diff % 1000
diff = (diff - milliseconds) / 1000
const seconds = diff % 60
diff = (diff - seconds) / 60
const minutes = diff % 60
diff = (diff - minutes) / 60
const hours = diff % 24
diff = (diff - hours) / 24
const days = diff
return {
days,
hours,
minutes,
seconds,
milliseconds
}
}
const targetDate = new Date('2019-11-29 00:00:00')
// Getting offset with getTimezoneOffset is not reliable, using a database to get time zone offset is needed, like IANA Time Zone Database.
// moment.js internally uses IANA db
const tzOffset = targetDate.getTimezoneOffset() // Client browsers timezone offset in minutes
const target_tzOffset = -600 // Australia Brisbane timezone offset in minutes
const offset = minToMS(tzOffset - target_tzOffset)
const msLeft = targetDate - new Date() - offset
const result = getCountDownFromMS(msLeft)
You should also check moment.js as it has many useful features.
Example with moment.js:
const now = moment()
const target = moment.tz('2019-11-29 00:00:00', 'Australia/Brisbane')
const result = moment.duration(target.diff(now))
does any one know this could be achieved in react native, I am working on an location based app that requires showing ETA to the customer. However, I do not want to show just 25mins away, I would like to implement 'arriving 'Arriving Today, 9:45 AM. which implies the current time is 9:20 and the ETA is added to the current time.
something like the image below
You can achieve it using the below function:
getETA(minutesLeftInArrival) {
let arrivalTimeLeft = minutesLeftInArrival * 60 * 1000; // convert to unix timestamp
let currentTime = Date.now(); //TIME RIGHT NOW
let timeToArrive = currentTime + arrivalTimeLeft; // TIME OF ARRIVAL
let time = new Date(timeToArrive).toTimeString(); // TIME in 24 hour format
time = time.split(" ")[0]; // Remove GMT+...... from time
time = time.replace(/:\d\d([ ap]|$)/,'$1'); // remove seconds from time
let H = +time.substr(0, 2);
let hour = H % 12 || 12;
let ampm = (H < 12 || H === 24) ? "AM" : "PM"; // Return AM or PM depedning of 24 Hour time
time = hour + time.substr(2, 3) + " " + ampm;
return time; // RETURNS 12 HOUR TIME
}
https://snack.expo.io/#ammarahmed/getetatime
I need to find the difference, in hours, between two values(t1 and t2)
t1(Now) code:
<td><!--tc:minutes--></td>
t2(then) code:
<td><!--tc:time.cost--></td>
For example t1 is 1:11 (1 hours, 11 minutes) and t2 is 1:05 (1 hours, 5 minutes)
How can I get the remaining time? 0:06 (0 hours, 6 minutes)? I think I need JavaScript function like HoursBetween in Delphi..
// using Date objects
var start = Date.now();
// the event to time goes here:
doSomethingForALongTime();
var end = Date.now();
var elapsed = end - start; // elapsed time in milliseconds
// using built-in methods
var start = new Date();
// the event to time goes here:
doSomethingForALongTime();
var end = new Date();
var elapsed = end.getTime() - start.getTime(); // elapsed time in milliseconds
// to test a function and get back its return
function printElapsedTime(fTest) {
var nStartTime = Date.now(),
vReturn = fTest(),
nEndTime = Date.now();
console.log('Elapsed time: ' + String(nEndTime - nStartTime) + ' milliseconds');
return vReturn;
}
yourFunctionReturn = printElapsedTime(yourFunction);