javascript - new - Cómo ignorar la zona horaria del usuario y forzar la fecha() utiliza la zona horaria específica
moment js (6)
El valor subyacente de un objeto Date está realmente en UTC. Para probar esto, observe que si escribe una new Date(0)
, verá algo así como: Wed Dec 31 1969 16:00:00 GMT-0800 (PST)
. 0 se trata como 0 en GMT, pero el método .toString()
muestra la hora local.
Nota importante, UTC significa código de tiempo universal . La hora actual en este momento en 2 lugares diferentes es la misma UTC, pero la salida se puede formatear de manera diferente.
Lo que necesitamos aquí es algún formato
var _date = new Date(1270544790922);
// outputs > "Tue Apr 06 2010 02:06:30 GMT-0700 (PDT)", for me
_date.toLocaleString(''fi-FI'', { timeZone: ''Europe/Helsinki'' });
// outputs > "6.4.2010 klo 12.06.30"
_date.toLocaleString(''en-US'', { timeZone: ''Europe/Helsinki'' });
// outputs > "4/6/2010, 12:06:30 PM"
Esto funciona, pero ... realmente no puedes usar ninguno de los otros métodos de fecha para tus propósitos ya que describen la zona horaria del usuario. Lo que quiere es un objeto de fecha que esté relacionado con la zona horaria de Helsinki. Sus opciones en este momento son usar una biblioteca de terceros (lo recomiendo), o modificar el objeto de fecha para que pueda usar la mayoría de sus métodos.
Opción 1: un tercero como momento-timezone
moment(1270544790922).tz(''Europe/Helsinki'').format(''YYYY-MM-DD HH:mm:ss'')
// outputs > 2010-04-06 12:06:30
moment(1270544790922).tz(''Europe/Helsinki'').hour()
// outputs > 12
Esto se ve mucho más elegante que lo que vamos a hacer a continuación.
Opción 2: piratear el objeto de fecha
var currentHelsinkiHoursOffset = 2; // sometimes it is 3
var date = new Date(1270544790922);
var helsenkiOffset = currentHelsinkiHoursOffset*60*60000;
var userOffset = _date.getTimezoneOffset()*60000; // [min*60000 = ms]
var helsenkiTime = new Date(date.getTime()+ helsenkiOffset + userOffset);
// Outputs > Tue Apr 06 2010 12:06:30 GMT-0700 (PDT)
Todavía cree que es GMT-0700 (PDT), pero si no miras demasiado, es posible que puedas confundirlo con un objeto de fecha que sea útil para tus propósitos.
Me salté convenientemente una parte. Necesita poder definir currentHelsinkiOffset
. Si puede usar date.getTimezoneOffset()
en el lado del servidor, o simplemente usar algunas sentencias if para describir cuándo ocurrirán los cambios en la zona horaria, eso debería resolver su problema.
Conclusión : creo que especialmente para este propósito debería usar una biblioteca de fechas como moment-timezone .
En una aplicación JS, recibo la marca de tiempo (por 1270544790922
) del servidor (Ajax).
Basándome en esa marca de tiempo, creo el objeto Date
usando:
var _date = new Date();
_date.setTime(1270544790922);
Ahora, _date
tiempo decodificada de fecha en la zona horaria local actual del usuario. No quiero eso.
Me gustaría _ date
para convertir esta marca de tiempo a la hora actual en la ciudad de Helsinki en Europa (sin tener en cuenta la zona horaria actual del usuario).
¿Cómo puedo hacer eso?
Para contabilizar milisegundos y la zona horaria del usuario, use lo siguiente:
var _userOffset = _date.getTimezoneOffset()*60*1000; // user''s offset time
var _centralOffset = 6*60*60*1000; // 6 for central time - use whatever you need
_date = new Date(_date.getTime() - _userOffset + _centralOffset); // redefine variable
Puede usar setUTCMilliseconds()
var _date = new Date();
_date.setUTCMilliseconds(1270544790922);
Solo otro enfoque
function parseTimestamp(timestampStr) {
return new Date(new Date(timestampStr).getTime() + (new Date().getTimezoneOffset() * 60 * 1000));
};
//Sun Jan 01 2017 12:00:00
var timestamp = 1483272000000;
date = parseTimestamp(timestamp);
document.write(date);
¡Aclamaciones!
Sospecho que la Answer no da el resultado correcto. En la pregunta, el asker quiere convertir la marca de tiempo del servidor a la hora actual en Hellsinki sin tener en cuenta la zona horaria actual del usuario.
Es el hecho de que la zona horaria del usuario puede ser lo que sea, por lo que no podemos confiar en ella.
Si, por ej. la marca de tiempo es 1270544790922 y tenemos una función:
var _date = new Date();
_date.setTime(1270544790922);
var _helsenkiOffset = 2*60*60;//maybe 3
var _userOffset = _date.getTimezoneOffset()*60*60;
var _helsenkiTime = new Date(_date.getTime()+_helsenkiOffset+_userOffset);
Cuando un neoyorquino visita la página, alerta (_helsenkiTime) imprime:
Tue Apr 06 2010 05:21:02 GMT-0400 (EDT)
Y cuando un finlandés visita la página, la alerta (_helsenkiTime) imprime:
Tue Apr 06 2010 11:55:50 GMT+0300 (EEST)
Por lo tanto, la función es correcta solo si el visitante de la página tiene la zona horaria objetivo (Europa / Helsinki) en su computadora, pero falla en casi todas las demás partes del mundo. Y dado que la marca de tiempo del servidor suele ser UNIX, que por definición está en UTC, el número de segundos desde Unix Epoch (1 de enero de 1970 00:00:00 GMT), no podemos determinar el horario de verano o el horario de verano a partir de la marca de tiempo.
Por lo tanto, la solución es DESREGAR el huso horario actual del usuario e implementar alguna forma de calcular el desplazamiento UTC independientemente de si la fecha está en horario de verano o no. Javascript no tiene un método nativo para determinar el historial de transición de DST de otra zona horaria que la zona horaria actual del usuario. Podemos lograr esto de la manera más simple usando el script del lado del servidor, porque tenemos acceso fácil a la base de datos de la zona horaria del servidor con todo el historial de transición de todas las zonas horarias.
Pero si no tiene acceso a la base de datos de la zona horaria del servidor (o de cualquier otro servidor) Y la marca de tiempo está en UTC, puede obtener la funcionalidad similar codificando las reglas DST en Javascript.
Para cubrir las fechas en los años 1998 - 2099 en Europa / Helsinki puede usar la siguiente función ( jsfiddled ):
function timestampToHellsinki(server_timestamp) {
function pad(num) {
num = num.toString();
if (num.length == 1) return "0" + num;
return num;
}
var _date = new Date();
_date.setTime(server_timestamp);
var _year = _date.getUTCFullYear();
// Return false, if DST rules have been different than nowadays:
if (_year<=1998 && _year>2099) return false;
// Calculate DST start day, it is the last sunday of March
var start_day = (31 - ((((5 * _year) / 4) + 4) % 7));
var SUMMER_start = new Date(Date.UTC(_year, 2, start_day, 1, 0, 0));
// Calculate DST end day, it is the last sunday of October
var end_day = (31 - ((((5 * _year) / 4) + 1) % 7))
var SUMMER_end = new Date(Date.UTC(_year, 9, end_day, 1, 0, 0));
// Check if the time is between SUMMER_start and SUMMER_end
// If the time is in summer, the offset is 2 hours
// else offset is 3 hours
var hellsinkiOffset = 2 * 60 * 60 * 1000;
if (_date > SUMMER_start && _date < SUMMER_end) hellsinkiOffset =
3 * 60 * 60 * 1000;
// Add server timestamp to midnight January 1, 1970
// Add Hellsinki offset to that
_date.setTime(server_timestamp + hellsinkiOffset);
var hellsinkiTime = pad(_date.getUTCDate()) + "." +
pad(_date.getUTCMonth()) + "." + _date.getUTCFullYear() +
" " + pad(_date.getUTCHours()) + ":" +
pad(_date.getUTCMinutes()) + ":" + pad(_date.getUTCSeconds());
return hellsinkiTime;
}
Ejemplos de uso:
var server_timestamp = 1270544790922;
document.getElementById("time").innerHTML = "The timestamp " +
server_timestamp + " is in Hellsinki " +
timestampToHellsinki(server_timestamp);
server_timestamp = 1349841923 * 1000;
document.getElementById("time").innerHTML += "<br><br>The timestamp " +
server_timestamp + " is in Hellsinki " + timestampToHellsinki(server_timestamp);
var now = new Date();
server_timestamp = now.getTime();
document.getElementById("time").innerHTML += "<br><br>The timestamp is now " +
server_timestamp + " and the current local time in Hellsinki is " +
timestampToHellsinki(server_timestamp);
Y esto imprime lo siguiente independientemente de la zona horaria del usuario:
The timestamp 1270544790922 is in Hellsinki 06.03.2010 12:06:30
The timestamp 1349841923000 is in Hellsinki 10.09.2012 07:05:23
The timestamp is now 1349853751034 and the current local time in Hellsinki is 10.09.2012 10:22:31
Por supuesto, si puede devolver la marca de tiempo en una forma que el desplazamiento (horario de verano o horario de verano) ya se haya agregado a la marca de tiempo en el servidor, no tiene que calcularlo en el lado del cliente y puede simplificar mucho la función. PERO recuerda NO usar timezoneOffset (), porque entonces tienes que tratar con la zona horaria del usuario y este no es el comportamiento deseado.
Suponiendo que obtenga la marca de tiempo en Helsinki, crearía un objeto de fecha configurado a la medianoche del 1 de enero de 1970 UTC (para ignorar la configuración de zona horaria local del navegador). Luego solo agrega la cantidad necesaria de milisegundos.
var _date = new Date( Date.UTC(1970, 0, 1, 0, 0, 0, 0) );
_date.setUTCMilliseconds(1270544790922);
alert(_date); //date shown shifted corresponding to local time settings
alert(_date.getUTCFullYear()); //the UTC year value
alert(_date.getUTCMonth()); //the UTC month value
alert(_date.getUTCDate()); //the UTC day of month value
alert(_date.getUTCHours()); //the UTC hour value
alert(_date.getUTCMinutes()); //the UTC minutes value
Tenga cuidado después, para preguntar siempre los valores UTC del objeto de fecha. De esta forma, los usuarios verán los mismos valores de fecha independientemente de la configuración local. De lo contrario, los valores de fecha se desplazarán según la configuración de hora local.