I have the following code taken from stack overflow:
function doSomething() {
var d = new Date(),
h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours() + 1, 0, 0, 0),
e = h - d;
window.setTimeout(doSomething, e);
//code to be run
alert("On the hour")
}
doSomething();
This works perfectly and produces an alert every hour on the hour. I would like the function to run every 15 minutes, at 00, 15, 30 and 45
I have the following code taken from stack overflow:
function doSomething() {
var d = new Date(),
h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours() + 1, 0, 0, 0),
e = h - d;
window.setTimeout(doSomething, e);
//code to be run
alert("On the hour")
}
doSomething();
This works perfectly and produces an alert every hour on the hour. I would like the function to run every 15 minutes, at 00, 15, 30 and 45
Share Improve this question edited Mar 21, 2013 at 14:35 Ian 50.9k13 gold badges103 silver badges111 bronze badges asked Mar 21, 2013 at 14:25 Alex McDaidAlex McDaid 2694 silver badges13 bronze badges4 Answers
Reset to default 14Get the time of the next even 15
minutes by:
(d.getMinutes() - (d.getMinutes() % 15)) + 15
On example when you invoke doSomething()
at 13:43, it will run next time at 13:45:
( 43 - (43 % 15) + 15 ) = ( 43 - 13 + 15 ) = 45
Then it will run as expected: 14:00, 14:15 and so on...
Complete code:
function doSomething() {
var d = new Date(),
h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), (d.getMinutes() - (d.getMinutes() % 15)) + 15, 0, 0),
e = h - d;
window.setTimeout(doSomething, e);
console.log('run');
}
doSomething();
This is a little trickier than others presented. You don't want 15 minutes from now, you want 15 minutes on the mark, starting with the next most recent. There are lots of ways to do it, but this one is what first jumps to my mind:
function doSomething() {
var d = new Date();
var minutes = 15 - d.getMinutes() % 15; // the number of minutes till the next 15.
window.setTimeout(doSomething, minutes * 60 * 1000);
//code to be run
alert("On the quarter-hour")
}
doSomething();
Give it a try. :-)
Edit
The above code is the simplest, but will have issues since it only looks at the minutes. It can drift by up to 59.999 seconds, and depending on processor load, may even show up occassionally on a 1, 16, 31, or 46. To make sure that doesn't happen, you do need to subtract:
function doSomething() {
var d = new Date();
var minutes = 15 - d.getMinutes() % 15; // the number of minutes till the next 15.
var h = new Date(d.getYear(), d.getMonth(), d.getDay(), d.getHours(), d.getMinutes() + minutes, 0);
var e = h-d;
window.setTimeout(doSomething, e);
//code to be run
alert("On the quarter-hour")
}
doSomething();
This keeps you precise to the second, while my original post was only precise to the minute.
Look at what the function is doing. You have a variable h
getting set to one hour after the current time.
//Gets the current date
var d = new Date()
//Note the +1
h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours() + 1, 0, 0, 0)
Each parameter in the Date
constructor corresponds to a time interval
new Date(year, month, day, hours, minutes, milliseconds)
Using this newly discovered bit of knowledge we can deduce that instead of adding one to the current hour, we need to add 15 minutes to the current time. The problem is that we can't just blindly add 15 minutes and think that we are all set because what we really want is to start on a quarter hour interval and only execute again on the next quarter hour.
In order to solve this conundrum we have to find out how far away we are from the next quarter interval, and set that as our timeout value.
var d = new Date();
var currentSeconds = d.getMinutes() * 60 + d.getSeconds();
var secondsFromQuarter = 900 - currentSeconds % 900;
Now we know how many seconds we need to wait to call doSomething
, but we must convert it to milliseconds.
var millisecondsFromQuarter = minutesFromQuarter * 1000;
Voila! From here we can call the setTimeout just like above with our millisecondsFromQuarter
value:
window.setTimeout(doSomething, millisecondsFromQuarter);
Disclaimer
This will be accurate to the second. If accuracy is needed to the millisecond then you would simply compare the millisecond value like so:
var currentMilliseconds = d.getMinutes() * 60 * 1000 + d.getSeconds() * 1000 + d.getMilliseconds();
var MillisecondsFromQuarter = 900000 - currentSeconds % 900000;
Disclaimer #2
I up-voted @kamituel's answer because it effectively does the same thing in a much cleaner way visually. I'm not sure which is better for performance but it's probably 6:6
function doSomething() {
var d = new Date(),
current_minutes = d.getMinutes(),
current_hour = d.getHours(),
next_min_hit = 0;
if ( current_minutes >= 0 && current_minutes < 15 )
next_min_hit = 15;
if ( current_minutes >= 15 && current_minutes < 30 )
next_min_hit = 30;
if ( current_minutes >= 30 && current_minutes < 45 )
next_min_hit = 45;
if ( current_minutes >= 45 && current_minutes < 59 ){
next_min_hit = 0;
current_hour++;
}
var h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), current_hour, next_min_hit , 0, 0),
e = h - d;
window.setTimeout(doSomething, e);
//code to be run
alert("On the hour")
}
doSomething();