admin管理员组

文章数量:1387303

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/puter 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>

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/puter 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>

Share Improve this question asked Mar 30, 2017 at 12:00 g5wxg5wx 7301 gold badge10 silver badges31 bronze badges 7
  • you should periodically query the servers time, not just a single time. – Daniel A. White Commented Mar 30, 2017 at 12:03
  • What is the problem with the user changing his local time? He can always break your page. – Bergi Commented Mar 30, 2017 at 12:03
  • Yeah, but i don't want the clock to change if it does. – g5wx Commented Mar 30, 2017 at 12:03
  • 1 Since your interval is every 1000ms, you could reasonably expect it to run within a small window of that value. Compare the Date.now() you get to whatever Date.now() you got last time around, and if it changes by an unexpected amount (more than 1.5s, less than 0.5s, or negative, for example) then re-request the time from the server to recalibrate. – Niet the Dark Absol Commented Mar 30, 2017 at 12:03
  • 1 Btw, you probably will want to use getUTCHours, getUTCMinutes and getUTCSeconds instead of the local ones that could be tinkered with already by a changing time zone. – Bergi Commented Mar 30, 2017 at 12:06
 |  Show 2 more ments

4 Answers 4

Reset to default 3

You should be able to pare 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)

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>

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

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));
    }

本文标签: Javascript clockserver timeStack Overflow