Frage:
Wie normalisieren Sie clientseitige Zeitstempel in Javascript für Benutzer, deren interne Computeruhren ausgeschaltet sind? Beachten Sie, dass ich mich mit Zeit in UTC beschäftige.
Kontext:
Ich habe eine AWS ElasticSearch-Instanz mit mehreren gestapelten und gedrosselten Vorgängen eingerichtet, wodurch serverseitige Zeitstempel unzuverlässig werden (da die Daten möglicherweise nicht in der richtigen Reihenfolge vorliegen und die Reihenfolge von Bedeutung ist). Ich muss daher meine clientseitigen Zeitstempel zuverlässiger machen.
Einschränkungen:
Ich kann keine serverseitigen Anforderungen stellen (HTTP-Anforderungen müssen auf ein Minimum beschränkt werden), aber ich kann einen serverseitigen Zeitstempel einfügen, der generiert wird, wenn mein Javascript zum ersten Mal auf den Client geladen wird.
Lösungsversuch:
Extern definierte Variablen:
serverTimestamp
- Ein UTC-Zeitstempel (in Millisekunden), der serverseitig generiert wird, wenn das Javascript geladen wird.getCookie
- Eine Funktion, die einen Cookie-Wert für einen bestimmten Schlüssel erhält (oder eine leere Zeichenfolge, wenn sie nicht gefunden wird).
Die Cache-Steuerungseinstellungen für die Datei sind "public,max-age=300,must-revalidate"
(also 5 Minuten).
const getTimestamp = (function() {
// This cookie is set on the `unload` event, and so should be greater than
// the server-side timestamp when set.
/** @type {!number} */
const cookieTimestamp = parseInt(getCookie("timestamp_cookie"), 10) || 0;
// This timestamp _should_ be a maximum of 5 minutes behind on page load
// (cache lasts 5 min for this file).
/** @type {!number} */
const storedTimestamp = cookieTimestamp > serverTimestamp ?
cookieTimestamp : serverTimestamp;
return function () {
/** @type {!number} */
const timestamp = Date.now();
// This timestamp should be, at a *maximum*, 5-6 minutes behind
// (assuming the user doesn't have caching issues)
/** @type {!number} */
const backupTimestamp = storedTimestamp
+ parseFloat(window.performance.now().toFixed(0));
// Now let's check to see if the user's clock is
// either too fast, or too slow:
if (
// Timestamp is smaller than the stored one.
// This means the user's clock is too slow.
timestamp < backupTimestamp
// Timestamp is more than 6 minutes ahead. User's clock is too fast.
// (Using 6 minutes instead of 5 to have 1 minute of padding)
|| (timestamp - backupTimestamp) > 360000
) {
return backupTimestamp;
} else {
// Seems like the user's clock isn't too fast or too slow
// (or just maximum 1 minute fast)
return timestamp;
}
}
})();
Problem mit der Lösung:
Mit der oben genannten getTimestamp
Funktion wird das Ausführen (new Date(getTimestamp())).getUTCDate()
für einige Benutzer am nächsten Tag zurückgegeben und getUTCHours
scheint in Randfällen allgegenwärtig zu sein. Ich kann das Problem nicht alleine diagnostizieren.
quelle
<?php date_default_timezone_set('UTC'); $o = new StdClass; if(isset($_POST['get_time'])){ /* make sure AJAX get_time is set */ $o->time = time(); echo json_encode($o); /* now you have object with time property for javascript AJAX argument */ } ?>
Antworten:
Halten Sie sich an die Zeitstempel auf der Client-Seite - kümmern Sie sich nicht um Datum / Uhrzeit. Speichern Sie das Delta zwischen der Serverseite und der Client-Uhr auf dem Client. Senden Sie den Client-Zeitstempel und das Delta mit den Nachrichten und rekonstruieren Sie dann Datum und Uhrzeit auf dem Server.
Dann können Sie auf der Serverseite sinnvolle Entscheidungen darüber treffen, wie Sie mit Jitter und Sprüngen in der Uhrensynchronisation umgehen sollen.
quelle
Sie sollten sich nicht für eine garantierte Zeit auf den Kunden verlassen. Ihr JavaScript könnte ungefähr so aussehen:
Bei Verwendung von PHP:
quelle