0

I want to detect a change in the value of Date().getSeconds() as soon as it happens.

I currently use:

function updateClock {
  ....
}
function detectChange(previousSec) {
  var currentSec = new Date().getSeconds();
  if (previousSec !== currentSec) {
    updateClock();
  }
}
setInterval(function () {
  var dat = new Date();
  var sec = dat.getSeconds;
  detectChange(sec);
}, 10);

Is there a better way to do this?

Thanks!

Irfanullah Jan
  • 3,336
  • 4
  • 24
  • 34
  • Explain your problem. Are you doing a game loop or something? Why check every 10ms to see if the time has changed? – Evan Trimboli Jan 16 '14 at 05:29
  • Why do you need to do this? The `getSeconds()`value is always going to change every second(or 1000ms). – tewathia Jan 16 '14 at 05:30
  • @EvanTrimboli It is a simple analog clock. http://codepen.io/irfan/pen/dIHoG – Irfanullah Jan Jan 16 '14 at 05:32
  • Isn't it obvious why you would use 10ms? checking only every 1000ms would mean you're possibly behind by almost 1 full second. Precision. – cwharris Jan 16 '14 at 05:52
  • 1
    Thanks a lot everyone! @ChristopherHarris I am ok with 10ms but I want to run the clock updating function only when there is increment in seconds value. – Irfanullah Jan Jan 16 '14 at 05:57
  • 2
    Hopefully we all agree that it's unlikely the client's system clock will be millisecond-synchronised with anything meaningful, e.g. the "standard" atomic clocks around the world. It's still an interesting question nonetheless. – Jeremy Jan 16 '14 at 06:07
  • Haha, yes. It's probably a moot point, but I think the underlying concept is important. :) – cwharris Jan 16 '14 at 06:14

3 Answers3

1

How about a 2-step process?

First, align your clock with the system's 0-millisecond mark

setTimeout(startClock, 1000 - (new Date()).getMilliseconds());

Then, you only need to tick once per second

function startClock() {
  setInterval(function do_your_thing() { ... }, 1000);
}

Practical demonstration (jsfiddle) shows that even if you do a large amount of work during the cycle, this method is pretty stable. In fact, on my machine you get better precision than the ±16ms resolution typically achievable in desktop task schedulers.

Community
  • 1
  • 1
Jeremy
  • 2,642
  • 18
  • 36
  • @ChristopherHarris that's true on some level, but my understanding is that `setInterval` *attempts* to call at exactly the interval you request. So it shouldn't get progressively later by the duration of `do_your_thing`, for example. – Jeremy Jan 16 '14 at 06:13
  • This I did not know. Do you have a reference for this? – cwharris Jan 16 '14 at 06:15
  • In practice, it's shifting at least 1 ms/s. – cwharris Jan 16 '14 at 06:18
  • @ChristopherHarris 1 ms/s is actually better than I expected. Also note that the drift seems random rather than biased, so over *n* seconds I'd expect an error of *O(sqrt[n])* ms. So a 250ms error would take about 17 hours. That's still pretty good IMO. – Jeremy Jan 16 '14 at 22:29
  • 1
    @ChristopherHarris [ref for earlier comment](http://ejohn.org/blog/how-javascript-timers-work/) - it's John Resig's explanation. – Jeremy Jan 16 '14 at 22:31
0

Unfortunately there is no standard event that fires when the clock changes seconds, so you'll need to set up an interval to detect it.

Setting an interval for every 1000ms means your clock could be off by almost a full second. Therefore I can understand why you'd want to check the seconds more than just once per second. The core concept here is sampling rate. The faster we sample the more precise we are, but the more processing time we waste detecting changes.

I think this will work for you.

function updateClock (date) {
  console.log(date);
};

(function () {

  var oldDate = new Date();

  return setInterval(function () {
    var date = new Date();
    if (date.getSeconds() != oldDate.getSeconds()) {
      updateClock(date);
    }
    oldDate = date;
  }, 10); // precision is ~10ms

})();
cwharris
  • 17,835
  • 4
  • 44
  • 64
-1

It will have a new value after every one second, therefore just put a timer with 1 second interval.

Ramesh Soni
  • 15,867
  • 28
  • 93
  • 113