Skip to content

Instantly share code, notes, and snippets.

@rkoshy
Last active February 3, 2023 10:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rkoshy/56fa2e80d446e4a675e4c31014fd003d to your computer and use it in GitHub Desktop.
Save rkoshy/56fa2e80d446e4a675e4c31014fd003d to your computer and use it in GitHub Desktop.
JS for simulating NTP time-sync. Original from: https://jehiah.cz/download/NTP.js, but didn't work - so this one has several edits
/*
NTP.js https://jehiah.cz/a/ntp-for-javascript
copyright Jehiah Czebotar jehiah@gmail.com
licensed under http://unlicense.org/ please modify as needed
to use configure serverUrl to an endpoint that when queried
(with X=timestamp_in_miliseconds)
GET serverUrl + '/' + X
returns a plain-text body:
(server_time_in_milliseconds - X) + ':' + X
*/
var NTP = {
cookieShelfLife: 3600, // 1 hour
requiredResponses: 10,
serverTimes: new Array,
serverUrl: "https://your-server/",
resyncTime: 10, // minutes
sync: function () {
// commented for testing
// if the time was set within the last x minutes; ignore this set request; time was synce recently enough
// var offset = NTP.getCookie("NTPClockOffset");
// if (offset){try{
// var t = offset.split("|")[1];
// var d = NTP.fixTime()-parseInt(t,10);
// if (d < (1000 * 60 * NTP.resyncTime)){return false;} // x minutes; return==skip
// }catch(e){}
// }
NTP.serverTimes = new Array;
NTP.getServerTime();
},
getNow: function () {
return Date.now();
},
parseServerResponse: function (data) {
var offset = parseInt(data.responseText.split(":")[0]);
var origtime = parseInt(data.responseText.split(":")[1]);
var delay = ((NTP.getNow() - origtime) / 2);
offset = offset - delay;
NTP.serverTimes.push(offset);
// if we have enough responces set cookie
if (NTP.serverTimes.length >= NTP.requiredResponses) {
// build average
var average = 0;
var i = 0;
for (i = 0; i < NTP.serverTimes.length; i++) {
average += NTP.serverTimes[i];
}
average = Math.round(average / i);
NTP.setCookie("NTPClockOffset", average); // set the new offset
console.log('Track fixTime', NTP.fixTime(), new Date(NTP.fixTime()).toString())
console.log('Track not fixTime', Date.now(), new Date(Date.now()).toString())
} else {
NTP.getServerTime();
}
},
getServerTime: function () {
try {
var xhr = new XMLHttpRequest();
// Making our connection
var url = NTP.serverUrl + Date.now();
xhr.open("GET", url, true);
// function execute after request is successful
xhr.onreadystatechange = function (res) {
if (this.readyState == 4 && this.status == 200) {
NTP.parseServerResponse({responseText: this.responseText});
}
}
// Sending our request
xhr.send();
} catch (e) {
return false;
//prototype.js not available
}
},
setCookie: function (aCookieName, aCookieValue) {
var date = new Date();
date.setTime(date.getTime() + (NTP.cookieShelfLife * 60 * 1000));
var expires = '; expires=' + date.toGMTString();
document.cookie = aCookieName + '=' + aCookieValue + expires + '; path=/';
},
getCookie: function (aCookieName) {
var crumbs = document.cookie.split('; ');
for (var i = 0; i < crumbs.length; i++) {
var crumb = crumbs[i].split('=');
if (crumb[0] == aCookieName && crumb[1] != null) {
return crumb[1];
}
}
return false;
},
fixTime: function (timeStamp) {
if (!timeStamp) {
timeStamp = NTP.getNow();
}
var offset = NTP.getCookie("NTPClockOffset");
try {
if (!offset) {
offset = 0;
}
temp = parseInt(offset, 10);
if (isNaN(temp)) {
return timeStamp;
}
return timeStamp + temp;
} catch (e) {
return timeStamp;
}
}
}
console.log('Track Before NTP.sync', NTP.fixTime(), new Date(NTP.fixTime()).toString())
setTimeout('NTP.sync()', 2500);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment