g5wx
g5wx

Reputation: 720

Javascript clock - server time

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>

Upvotes: 3

Views: 4771

Answers (4)

Dilip Barnwal
Dilip Barnwal

Reputation: 1

More Updated with AM & PM

var serverTime = 1490856278000;
    var expected = serverTime;
    var date;
    var h;
    var m;
    var s;
    var now = performance.now();
    var then = now;
    var dt = 0;
    var nextInterval = (interval = 1000);

    setTimeout(step, interval);
    function step() {
      then = now;
      now = performance.now();
      dt = now - then - nextInterval;
      nextInterval = interval - dt;
      serverTime += interval;
      date = new Date(serverTime);
      h = date.getHours();
      m = date.getMinutes();
      s = date.getSeconds();

      var session = "AM";

      if (h == 0) {
        h = 12;
      }

      if (h > 12) {
        h = h - 12;
        session = "PM";
      }

      h = h < 10 ? "0" + h : h;
      m = m < 10 ? "0" + m : m;
      s = s < 10 ? "0" + s : s;

      var time = h + ":" + m + ":" + s + " " + session;

      document.getElementById("NowTime").innerHTML = time;

      now = performance.now();

      setTimeout(step, Math.max(0, nextInterval));
    }

Upvotes: 0

Oskar
Oskar

Reputation: 2607

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>

Upvotes: 2

Bergi
Bergi

Reputation: 664297

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)

Upvotes: 3

Panomosh
Panomosh

Reputation: 892

The time will change because Date.now(); is getting it's time from the Client machine. There are no AJAX calls in your script.

Upvotes: 0

Related Questions