Pregunta:
¿Cómo normaliza las marcas de tiempo del lado del cliente en javascript para los usuarios cuyos relojes internos de la computadora están apagados? Tenga en cuenta que estoy lidiando con el tiempo en UTC.
Contexto:
Tengo una instancia de AWS ElasticSearch configurada con varias operaciones por lotes y estranguladas en el camino, lo que hace que las marcas de tiempo del lado del servidor no sean confiables (ya que los datos pueden estar fuera de servicio y el orden importa). Por lo tanto, necesito hacer que mis marcas de tiempo del lado del cliente sean más confiables.
Restricciones:
No puedo hacer ninguna solicitud del lado del servidor (necesito mantener las solicitudes HTTP al mínimo), pero puedo incluir una marca de tiempo del lado del servidor generada cuando mi javascript se carga por primera vez en el cliente.
Intento de solución:
Variables definidas externamente:
serverTimestamp
- una marca de tiempo UTC (en milisegundos), generada en el lado del servidor cuando se carga el javascript.getCookie
- una función que obtiene un valor de cookie para una clave determinada (o una cadena vacía si no se encuentra).
La configuración de control de caché para el archivo es "public,max-age=300,must-revalidate"
(por lo tanto, 5 minutos).
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;
}
}
})();
Problema con la solución:
Usando la getTimestamp
función anterior , la ejecución (new Date(getTimestamp())).getUTCDate()
regresa al día siguiente para algunos usuarios, y getUTCHours
parece estar por todos lados en casos extremos. No puedo diagnosticar el problema por mi cuenta.
fuente
<?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 */ } ?>
Respuestas:
Apéguese a las marcas de tiempo en el lado del cliente, no se moleste con las fechas / horas. Almacene el delta entre el lado del servidor y el reloj del cliente en el cliente. Envíe la marca de tiempo y delta del cliente con los mensajes y luego reconstruya la fecha / hora en el servidor.
Luego, puede tomar decisiones sensatas en el servidor sobre cómo lidiar con las fluctuaciones y los saltos en la sincronización del reloj.
fuente
No debe confiar en el Cliente por tiempo garantizado. Su JavaScript puede parecerse a algo como:
Si usa PHP:
fuente