servidor reloj para obtener internet hora fecha cronometro codigo analogico actual javascript ajax timezone clock-synchronization

para - La mejor forma de sincronizar el reloj javascript del lado del cliente con la fecha del servidor



reloj analogico javascript (7)

Descubrí que el algoritmo de @mehdi-yeganeh anterior no me proporcionaba resultados útiles, pero la idea es acertada: usar el algoritmo NTP (o al menos una versión débil) para sincronizar el servidor y los relojes del cliente.

Esta es mi implementación final, usa los encabezados de respuesta del servidor si están disponibles para mayor precisión (corríjanme si me equivoco, mis propias pruebas dicen que esto es bastante preciso).

lado del navegador (javascript):

// the NTP algorithm // t0 is the client''s timestamp of the request packet transmission, // t1 is the server''s timestamp of the request packet reception, // t2 is the server''s timestamp of the response packet transmission and // t3 is the client''s timestamp of the response packet reception. function ntp(t0, t1, t2, t3) { return { roundtripdelay: (t3 - t0) - (t2 - t1), offset: ((t1 - t0) + (t2 - t3)) / 2 }; } // calculate the difference in seconds between the client and server clocks, use // the NTP algorithm, see: http://en.wikipedia.org/wiki/Network_Time_Protocol#Clock_synchronization_algorithm var t0 = (new Date()).valueOf(); $.ajax({ url: ''/ntp'', success: function(servertime, text, resp) { // NOTE: t2 isn''t entirely accurate because we''re assuming that the server spends 0ms on processing. // (t1 isn''t accurate either, as there''s bound to have been some processing before that, but we can''t avoid that) var t1 = servertime, t2 = servertime, t3 = (new Date()).valueOf(); // we can get a more accurate version of t2 if the server''s response // contains a Date header, which it generally will. // EDIT: as @Ariel rightly notes, the HTTP Date header only has // second resolution, thus using it will actually make the calculated // result worse. For higher accuracy, one would thus have to // return an extra header with a higher-resolution time. This // could be done with nginx for example: // http://nginx.org/en/docs/http/ngx_http_core_module.html // var date = resp.getResponseHeader("Date"); // if (date) { // t2 = (new Date(date)).valueOf(); // } var c = ntp(t0, t1, t2, t3); // log the calculated value rtt and time driff so we can manually verify if they make sense console.log("NTP delay:", c.roundtripdelay, "NTP offset:", c.offset, "corrected: ", (new Date(t3 + c.offset))); } });

lado del servidor (php, pero podría ser cualquier cosa):

Su servidor en la ruta ''GET / ntp'' debería devolver algo como:

echo (string) round(microtime(true) * 1000);

Si tiene PHP> 5.4, puede guardar una llamada a microtime () y hacerlo un poco más preciso con:

echo (string) round($_SERVER[''REQUEST_TIME_FLOAT''] * 1000);

NOTA

De esta manera se puede ver como una especie de gueto, hay algunas otras respuestas de desbordamiento de pila que podrían guiarlo hacia una mejor solución:

Tengo una tarea para mostrar el reloj digital (con minutos de precisión) en la página HTML en una zona horaria fija (MSK o MSD, dependiendo de la fecha actual). Me gustaría evitar confiar en el reloj del sistema cliente, por lo que se requiere alguna sincronización con el servidor. El servidor HTTP envía el encabezado Fecha en cada respuesta para que podamos enviar una solicitud AJAX GET o HEAD a cualquier URL de nuestro sitio para obtener la fecha del servidor, calcular la diferencia con la fecha del cliente y usarla al actualizar el reloj con setTimeout (). Quedan otros problemas: cambio de zona horaria para configuraciones de luz natural, contabilidad de latencia para conexiones muy lentas.

¿Alguna idea para esta tarea de la manera más simple? Prefiero resolverlo sin la programación del lado del servidor.


Estas dos funciones de Javascript deberían hacer el truco para ti.

var offset = 0; function calcOffset() { var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); xmlhttp.open("GET", "http://.com/", false); xmlhttp.send(); var dateStr = xmlhttp.getResponseHeader(''Date''); var serverTimeMillisGMT = Date.parse(new Date(Date.parse(dateStr)).toUTCString()); var localMillisUTC = Date.parse(new Date().toUTCString()); offset = serverTimeMillisGMT - localMillisUTC; } function getServerTime() { var date = new Date(); date.setTime(date.getTime() + offset); return date; }

EDITAR: eliminó ".replace (/ ^ (. ) [/ S / S] /," $ 1 ")".

calcOffset () calcula el desplazamiento desde el tiempo del servidor y compensa por GMT / UTC.

getServerTime () para obtener el desplazamiento de hora local para que coincida con los servidores, utilizando la zona horaria local.

Si calcOffset () tarda bastante en ejecutarse, es posible que pierda algunos segundos de precisión. Tal vez el tiempo de ejecución podría tenerse en cuenta ...

Si le preocupa que la compensación calculada se vuelva incorrecta cuando la hora local o la hora del servidor cambian hacia o desde el horario de verano, puede recalcular un poco después de cada hora, el sistema compensará los cambios en el horario de ahorro diario. Es posible que sea necesario esperar hasta que el reloj local y el servidor hayan pasado la hora.

El ejemplo solo funciona en IE debido a "Msxml2.XMLHTTP", creo ...



Puede calcular la hora exacta con NTP (Network Time Protocol) en sus códigos,

Trato de explicarte:

  1. Tenemos ClientTime en la solicitud de envío (por ejemplo, 4/3/2012 13: 56: 10.123)
  2. Usted envía ClientTime al servidor
  3. Tenemos tiempo de ida y vuelta para la solicitud, lo llamé RequestTime (por ejemplo: toma 5 segundos)
  4. En el servidor, calculamos el tiempo de diferencia entre el servidor y el cliente (por ejemplo: ServerTime - ClientTime = ServerClientDifferenceTimeWithRequestTime), ahora debería incluir esta diferencia, incluido el tiempo de solicitud de ida y vuelta en el paso 3, y luego eliminar el tiempo de ida y vuelta de la diferencia
  5. Respuesta de envío de servidor que incluye ServerClientDifferenceTimeWithRequestTime y ServerTime
  6. Tenemos un tiempo de ida y vuelta para la respuesta, lo llamé ResponseTime (por ejemplo: toma 3 segundos)
  7. En el cliente, calculamos el tiempo de diferencia entre el servidor y el cliente nuevamente (por ejemplo: ServerTime - ClientTime = ServerClientDifferenceTimeWithResponseTime), de nuevo: ahora debería incluir esta diferencia, incluido el tiempo de respuesta de ida y vuelta en el paso 6
  8. Ahora tenemos tiempo en el cliente
  9. Deberías calcular ecuaciones simples en el cliente:

X (SyncedTime) = Now + (ServerClientDifferenceTimeWithRequestTime - RquestTime)

X (SyncedTime) = Now + (ServerClientDifferenceTimeWithResponseTime - ResponseTime)

Now - ClientTime = RquestTime + ResponseTime =>

Now - (ServerClientDiffRq - RquestTime) = Now - (ServerClientDiffRs - ResponseTime)

si lo resuelves, encontraste esto:

ResponseTime = (ServerClientDifferenceTimeWithRequestTime - Now + ClientTime + - ServerClientDifferenceTimeWithResponseTime )/2

y luego puede encontrar el tiempo sincronizado o el tiempo del servidor en el cliente con esta ecuación:

X (SyncedTime) = Now + (ServerClientDifferenceTimeWithResponseTime - ResponseTime)

Muestro código simple, pero cuando quiera escribirlo, no olvide utilizar las funciones de fecha y hora de UTC ...

Lado del servidor (por ejemplo php, c #):

PHP:

header(''Content-Type: application/json; charset=utf-8''); $clientTime = $_GET["ct"] * 1; //for php 5.2.1 or up: (float)$_GET["ct"]; $serverTimestamp = round(microtime(true)*1000); // (new DateTime())->getTimestamp(); $serverClientRequestDiffTime = $serverTimestamp - $clientTime; echo "{/"diff/":$serverClientRequestDiffTime,/"serverTimestamp/":$serverTimestamp}";

DO#:

long clientTime = long.Parse(Request.Form["ct"]); long serverTimestamp = (DateTime.Now.Ticks-(new DateTime(1970,1,1) - DateTime.MinValue).Ticks) / 10000; long serverClientRequestDiffTime = serverTimestamp - clientTime; Response.Write("{/"diff/":"+serverClientRequestDiffTime+",/"serverTimestamp/":"+serverTimestamp+"}");

Lado del cliente (Javascript con Jquery ):

var clientTimestamp = (new Date()).valueOf(); $.getJSON(''http://yourhost.com/getdatetimejson/?ct=''+clientTimestamp, function( data ) { var nowTimeStamp = (new Date()).valueOf(); var serverClientRequestDiffTime = data.diff; var serverTimestamp = data.serverTimestamp; var serverClientResponseDiffTime = nowTimeStamp - serverTimestamp; var responseTime = (serverClientRequestDiffTime - nowTimeStamp + clientTimestamp - serverClientResponseDiffTime )/2 var syncedServerTime = new Date((new Date()).valueOf() + (serverClientResponseDiffTime - responseTime)); alert(syncedServerTime); });


Solo solicitaría la actualización desde el servidor cada 30 s más o menos, si requiere precisión solo minuto a minuto. No confíe en el tiempo del cliente, pero use el reloj de su sistema para mantener el reloj preciso entre las actualizaciones. ¿Creo que respondiste tu propia pregunta?

Ayudaría si entendiéramos mejor lo que realmente estás tratando de hacer.

Si simplemente desea que un reloj muestre la hora en el servidor, que luego se ajusta a una determinada zona horaria, hágalo desde el lado del cliente con compensaciones. Controle el horario de verano (DST) en las zonas horarias que corresponda utilizando también la fecha que recibe del servidor. Si desea determinar la latencia, probablemente necesite una pequeña secuencia de comandos en el servidor para calcular la diferencia. Pero como se indicó anteriormente, ayudaría a comprender mejor el problema. Si la precisión es solo por minuto, la latencia parece menos crítica.



debe recordar el tiempo del cliente entre readyState == 2 y readyState == 3 si va a usar ajax, porque el tiempo del servidor se establecerá en algún lugar entre el tiempo a petición recibida y la respuesta preparada