15

I've been developing a web application Dashboard and I was wondering how to detect that is midnight in order to reset some arrays that contains datas from the previous day using jquery or momentjs.

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
Juan Jardim
  • 2,232
  • 6
  • 28
  • 46
  • Are you talking about server or client? I'm not sure you want to do it on client... – Ionică Bizău Oct 15 '14 at 16:07
  • I'm talking about the client. The only thing I don't want is to refresh the page. What I want for instance is this: imaging that you have an array with data, i want to reset this array. I also don't want to check (If possible) every 5 seconds if is midnigth – Juan Jardim Oct 15 '14 at 16:07
  • Ok, how do you define *midnight*? Is this `0:00` hour? – Ionică Bizău Oct 15 '14 at 16:09
  • Midnight is 0, but there are problems with detecting midnight. Best course of action is to re-think your application goals, and move on from the task. `if(is_midnight())` midnight returns 0, so logically it would be false – Ryan Oct 15 '14 at 16:11
  • @JuanJardim I added my answer. Try to change `midnight` variable and see the result. – Ionică Bizău Oct 15 '14 at 16:16
  • @Ionică Bizău, thank you. but check every second if is midnight i think its not a good solution in terms of performance. But this give me an ideia: check how many seconds left to midnight and the initialise a set interval to trigger your function. After that I would restart the set interval trigger with the new count. – Juan Jardim Oct 15 '14 at 16:27
  • @JuanJardim - Why didn't *I* think of that ;) – Jamiec Oct 15 '14 at 16:38
  • @JuanJardim I agree. Moment has nice functions for that. See updated answer. – Ionică Bizău Oct 15 '14 at 17:16

5 Answers5

19

Use moment().format("h:mm:ss") that returns time in a h:mm:ss format.

var midnight = "0:00:00";
var now = null;

setInterval(function () {
    now = moment().format("H:mm:ss");
    if (now === midnight) {
        alert("Hi");
    }
    $("#time").text(now);
}, 1000);

JSFIDDLE

A better way would be to compute the seconds until midnight. This is very simple and human readable using MomentJS:

// returns the number of seconds until next midnight
moment("24:00:00", "hh:mm:ss").diff(moment(), 'seconds');

So, just do:

setTimeout(
   midnightTask,
   moment("24:00:00", "hh:mm:ss").diff(moment(), 'seconds')
);

function midnightTask() {
  /* do something */
}

JSFIDDLE

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
  • The second solution (setTimeout) will not work if the computer goes to sleep and resumes much later. In such cases the trigger will be delayed with about as much time as the computer spent in sleep mode. – András Szepesházi Jan 15 '18 at 10:33
  • 1
    "h" gives you 12-hour format, so `moment().format("h:mm:ss")` will be "12:00:00" at midnight. Checking "HH:mm:ss" against "00:00:00" should work. – Dunc Jun 28 '18 at 15:39
  • @Dunc Whoups! Thanks a lot! :D – Ionică Bizău Jun 28 '18 at 15:55
6

There's only really two ways to accomplish this

  1. poll every x seconds and see whether we're within x seconds of midnight
  2. Calculate the time between now and midnight, and sleep for that amount of time before executing

(1) has been demonstrated in other answers, here's (2).

The first thing to do is calculate the number of milliseconds until midnight then use that as a parameter to javascripts setTimeout.

setTimeout(function(){
  // whatever you want to do at midnight
}, msToMidnight);

After you've finished your work in that function, you might want to recaculate the time until next midnight and repeat the process.

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • What happens if the computer sleeps? Will setTimeout be off by the amount that it sleeps? Polling seems to be the better approach here. – vrspiration Jul 23 '22 at 18:46
4

So I think you're going about this the wrong way. What you're looking for isn't when it's midnight, you just want to know when the day has changed, which is a much simpler task.

The first thing I'm going to say is avoid using timers at all costs. They're not worth it. The performance hit and extra CPU time you take from running the same function >3600 times a day is ridiculous, especially when it's running on someone else's computer. You don't know how much it can handle, so assume it can't handle much at all. Go easy on your users.

I would suggest listening to a user input event, assuming that this is something you would have on a regular computer, and not something like this, where there is no user input.

If user input events are something you could rely on, I would do this..

var today = new Date(), lastUpdate;

window.addEventListener( "mousemove", function () {
  var time = new Date();
  // If we haven't checked yet, or if it's been more than 30 seconds since the last check
  if ( !lastUpdate || ( time.getTime() - lastUpdate.getTime() ) > 30000 ) {
    // Set the last time we checked, and then check if the date has changed.
    lastUpdate = time
    if ( time.getDate() !== today.getDate() ) {
      // If the date has changed, set the date to the new date, and refresh stuff.
      today = time

      this_is_where_you_would_reset_stuff()
    }
  }
} )

If you absolutely need to use a timer, then I would do this..

function init() {
  var today = new Date();
  var midnight = new Date();

  midnight.setDate( today.getDate() + 1 )
  midnight.setHours( 0 )
  midnight.setMinutes( 0 )

  setTimeout( function () {
    // If the date has changed, set the date to the new date, and refresh stuff.
    today = time

    this_is_where_you_would_reset_stuff()

    init()
  }, midnight.getTime() - today.getTime() )
}

init()

Keep in mind that the second way is likely to be far less reliable.

McKayla
  • 6,879
  • 5
  • 36
  • 48
  • The problem with this approach is that this dashboard is to display in a monitor an the user sees only the data changing. But thank you for your suggestion – Juan Jardim Oct 15 '14 at 19:22
  • 4
    This queries the system timer every time the mouse moves. This is the last thing you want to be doing. Even the creation of the Date object itself is more than you want to be doing just because the mouse moved. – Adam Leggett Oct 25 '18 at 21:11
1

Create a date at midnight this morning, add 86400 seconds, and set a timeout for then:

new Date(Date.parse((new Date()).toString().replace(/\d\d:\d\d:\d\d/,'00:00:00')) + 86400 * 1000)

Here's how you'd use it:

var delay_to_midnight = Date.parse((new Date()).toString().replace(/\d\d:\d\d:\d\d/,'00:00:00')) + 86400 * 1000 - Date.now()
var timeoutid = window.setTimeout(function() { alert("It's midnight!"); }, delay_to_midnight);
Michael Chaney
  • 2,911
  • 19
  • 26
0

I would try:

window.setInterval(resetAtMidnight, 1000*5) // every five seconds
function resetAtMidnight() {
  var now = new Date();
  if(now.getHours() < 1
   && now.getMinutes() < 1
   && now.getSeconds() < 5 ) {
    redrawPage();
  }
};
wk_
  • 301
  • 2
  • 8
Plato
  • 10,812
  • 2
  • 41
  • 61