Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript clock - server time

Tags:

javascript

I need to show the server time on a clock. Below is the code i currently have. I get the server time with Ajax call. The problem is that if the user changes it's local/computer clock it will also update the script's clock which is not ok - it should continue without changing and i'm stuck. I've tried passing the serverTime within the setTimeout so it get's used every time as a reference but no luck with that.

var serverTime  = 1490856278000;
var localTime   = +Date.now();
var timeDiff    = serverTime - localTime;
var realTime;
var date;
var hours;
var minutes;
var seconds;
setInterval(function () {
  realTime = +Date.now() + timeDiff;
  date     = new Date(realTime);
  hours    = date.getHours();
  minutes  = date.getMinutes();
  seconds  = date.getSeconds();
  document.getElementById('clock').innerHTML = hours + ':' + minutes + ':' + seconds;
}, 1000);
<div id="clock"></div>
like image 555
g5wx Avatar asked Aug 06 '26 14:08

g5wx


2 Answers

You should be able to compare each realTime with the last one in your setInterval. If the difference is far from the 1000ms that it is supposed to be, do an ajax call to query the server time again and renew the timeDiff.


Also you can try to use performance.now instead of Date.now. The higher resolution is unnecessary and possibly expensive, but MDN states that

unlike Date.now(), the values returned by Performance.now() always increase at a constant rate, independent of the system clock (which might be adjusted manually or skewed by software like NTP)

like image 59
Bergi Avatar answered Aug 09 '26 02:08

Bergi


Using How to create an accurate timer in javascript? and Bergi's answer I prepared an another way. I think you don't have to use the local time at all:

var serverTime  = 1490856278000;
var expected = serverTime;
var date;
var hours;
var minutes;
var seconds;
var now = performance.now();
var then = now;
var dt = 0;
var nextInterval = interval = 1000; // ms

setTimeout(step, interval);
function step() {
    then = now;
    now = performance.now();
    dt = now - then - nextInterval; // the drift
    
    nextInterval = interval - dt;
    serverTime += interval;
    date     = new Date(serverTime);
    hours    = date.getUTCHours();
    minutes  = date.getUTCMinutes();
    seconds  = date.getUTCSeconds();
    document.getElementById('clock').innerHTML = hours + ':' + minutes + ':' + seconds;

    console.log(nextInterval, dt); //Click away to another tab and check the logs after a while
    now = performance.now();

    setTimeout(step, Math.max(0, nextInterval)); // take into account drift
}
<div id="clock"></div>
like image 29
Oskar Avatar answered Aug 09 '26 04:08

Oskar