How to run a function at specific time & date?

29,348

Solution 1

It's not advised to use setInterval because it has non-deterministic behaviour - events can be missed, or fire all at once. Time will fall out of sync, too.

The code below instead uses setTimeout with a one minute period, where each minute the timer is resynchronised so as to fall as closely to the hh:mm:00.000s point as possible.

function surprise(cb) {
    (function loop() {
        var now = new Date();
        if (now.getDate() === 12 && now.getHours() === 12 && now.getMinutes() === 0) {
            cb();
        }
        now = new Date();                  // allow for time passing
        var delay = 60000 - (now % 60000); // exact ms to next minute interval
        setTimeout(loop, delay);
    })();
}

Solution 2

On the page where o want to do the check add this

setInterval(function () {
    var date = new Date();
    if (date.getDate() === 12 && date.getHours() === 10 && date.getMinutes === 0) {
        alert("Surprise!!")
    }
}, 1000)

FIDDLE


Update- add date.getSeconds == 0 to limit it to fire only one at 10:00:00. Thanks to comments below

Solution 3

You can instantiate two Date objects. One for now and one for the next instance of the event. Now is easy: new Date(). For the next instance you can loop through the options till you find one larger than now. Or do some more sophisticated date time wizardry. Compare the getTime() of the both, and then do a setTimeout for the alert.

EDIT: Updated since @Alnitak points out that there's a maximum to the timeout, see setTimeout fires immediately if the delay more than 2147483648 milliseconds.

function scheduleMessage() {
    var today=new Date()

    //compute the date you wish to show the message
    var christmas=new Date(today.getFullYear(), 11, 25)
    if (today.getMonth()==11 && today.getDate()>25)
        christmas.setFullYear(christmas.getFullYear()+1)

    var timeout = christmas.getTime()-today.getTime();
    if( timeout > 2147483647 ){
        window.setTimeout( scheduleMessage(), 2147483647 )
    } else {
        window.setTimeout(function() {alert('Ho Ho Ho!'); scheduleMessage()}, timeout)
    }
}

Solution 4

You can use something like this

var runned = false;
var d = new Date();
if(d.getDate() == 12 && d.getHours() == 10 && !runned){
    //Do some magic
    runned = true;
}

If you want some with the minute (and not the whole hour you can add d.getMinutes()

Share:
29,348
Shannon Hochkins
Author by

Shannon Hochkins

Passionate about learning new things, constantly working on my own projects to achieve that goal.

Updated on January 15, 2020

Comments

  • Shannon Hochkins
    Shannon Hochkins over 4 years

    How can I run a function at a given time and date?

    Example: I have a function that needs to run on the 12th of each month at 10AM.

    This page will be running 24/7, if this is important.

    Obviously I'd have to compare against the current date, but I'm not sure how to check if the current date and time has been matched.

    Shannon

  • Alnitak
    Alnitak over 10 years
    this code has bugs, one visible, and one invisible. The invisible bug is that it'll repeatedly show the alert over and over so until the time reaches 10:01.
  • Shannon Hochkins
    Shannon Hochkins over 10 years
    @Alnitak, again, you're commenting based on an assumption that I wanted to run the function only once, and also it's not upto the user to completely write the code, it's fairly obvious and simply to clear the interval once it's passed.
  • Alnitak
    Alnitak over 10 years
    @ShannonHochkins if you clear the interval it won't fire next month (assuming the page isn't reloaded between times).
  • Alnitak
    Alnitak over 10 years
    for == '12' - the output of .getDate() is a number
  • Kasper Sanguesa-Franz
    Kasper Sanguesa-Franz over 10 years
    woops that went a bit fast there, fixed now :)
  • Shannon Hochkins
    Shannon Hochkins over 10 years
    That's quite interesting! So I'm assuming that cb, that you're passing to the surprise function, is also a function? Meaning that you run this like so: surprise(otherFunctionName);. Do you mind me asking why you do it this way?
  • Alnitak
    Alnitak over 10 years
    Yes, that's right - the "why" is called "separation of concerns" - separating the "when" you want something to happen from the "what".
  • Shannon Hochkins
    Shannon Hochkins over 10 years
    Where you're using Modula to calculate the remainder of milliseconds, do you agree it would be more useful putting the minute value in milliseconds as a variable? It would read a bit nicer too I guess, but I do like your solution, it should would quite nicely.
  • flup
    flup over 10 years
    I think this way you can be unlucky and miss the exact second you're waiting for, scheduling is not that precise. It could be the first one gets scheduled at 11:59:59.999 and the next one at 12:00:01.000
  • Alnitak
    Alnitak over 10 years
    @ShannonHochkins re: 60s - I'd say at your discretion. Personally I read 60000 and the conversion is instantaneous. Note that even this method is not without risk - if the system clock is adjusted underneath this code the timer could fire when the time isn't quite (yet) 10:00:xx. It's actually pretty hard to mitigate that, though!
  • Shannon Hochkins
    Shannon Hochkins over 10 years
    Cool, no worries @Alnitak, thankyou for your post, just a quick question though, if I was to do this server side rather than client side, is there a way to still have a user interface on the webpage to 'pick' the time, and still correctly start a timer without having the page constantly open? Probably not right..
  • flup
    flup over 10 years
    Now take the final step and don't loop, but set only one timeout, to the exact moment you're waiting for. (And end up at my answer ;) )
  • Alnitak
    Alnitak over 10 years
    @flup there are limits as to how far in the future you can do a single setTimeout call.
  • Alnitak
    Alnitak over 10 years
    @ShannonHochkins that's getting towards the point I was making in my original comments - the page has to be open to do anything, because that's where the JS runs. Now, if you want to specify a time, and then have stuff work if the page is reloaded, you'd have to get into cookies, localStorage, that sort of thing, to restore the page's state on reload.
  • flup
    flup over 10 years
    @Alnitak I didn't know that, thanks! It seems risky to me to aim for the exact changing of the minute. If you get scheduled a little early, your first check might hit 11:59:59.999 and decide it is not yet time. The second check lands at 12:00:00.001 and decides to wait for another minute. You should probably aim for the halfway point instead.
  • Alnitak
    Alnitak over 10 years
    @flup yeah, one approach is to check for "time < target" changing to "time >= target", but in extremis as you say it'll then wait to 10:01. I'll look at that again.