new - obtener zona horaria javascript
Trabajar con zonas horarias y horario de verano en Javascript (3)
Mi aplicación javascript de una sola página recupera datos en formato JSON a través de llamadas REST. Las fechas vienen formateadas utilizando la zona horaria UTC en formato estándar ISO8601, como 2011-02-04T19:31:09Z
.
Al registrarse en el servicio, los usuarios seleccionan su zona horaria de una lista desplegable. Esta zona horaria podría ser diferente a la zona horaria del navegador del usuario. La aplicación javascript sabe cuál es la zona horaria seleccionada por el usuario en todo momento.
Sé cómo convertir la cadena UTC en una fecha. Entiendo que Javascript solo representa fechas en la zona horaria local.
Pero estoy teniendo problemas para averiguar cómo mostrar una fecha formateada para una zona horaria OTRA a la zona horaria local del usuario . Debe tener en cuenta el horario de verano en todas las fechas. Internamente, quiero tratar todas las fechas como UTC y solo convertirlas a una representación de cadena de una fecha en otra zona horaria en el momento de la visualización. Necesito mostrar las fechas en la zona horaria seleccionada en el perfil del usuario, no en la zona horaria de su navegador.
He experimentado con el servidor enviando la diferencia de desplazamiento de la zona horaria en milisegundos entre la zona horaria del navegador del usuario y la zona horaria del perfil del usuario. Pero he descubierto que no puedo simplemente enviar un valor de compensación, sino que debo enviar una compensación por cada fecha para tener en cuenta las variaciones en el horario de verano.
¿Alguna sugerencia o código de muestra sobre cómo mostrar fechas formateadas en varias zonas horarias? Las opciones que he encontrado hasta ahora:
- El servidor envía las fechas como cadenas ya formateadas en la zona horaria correcta y no se realiza ningún análisis de fecha o manipulación en el cliente. Esto hace que hacer ciertas cosas en el cliente sea difícil, si no imposible.
- Utilice una biblioteca como https://github.com/mde/timezone-js , que incluye toda la base de datos Olson TZ en Javascript. Esto significa más tiempo de carga más uso de memoria, etc.
- Envíe un valor de timezoneOffsetMillis con cada fecha enviada al cliente. Esto da como resultado datos JSON desordenados e interfaces REST no óptimas.
¿Hay alguna solución más simple o mejor?
2 es una mala idea ya que, como usted señaló, aumenta los tiempos de carga. Si fuera usted, haría una combinación de 1 y 3. No estoy de acuerdo con que esto desordene los datos JSON o la interfaz REST.
Este es un compromiso clásico donde aceptar un poco más de complejidad en el protocolo para simplificar el código del lado del cliente.
Avance rápido hasta 2015, cuando se trata de formatear una fecha de otra zona horaria, usando una configuración regional específica , hay dos opciones.
En el ejemplo, uso la configuración regional en francés y usaré una fecha (UTC + 5) del 27 de marzo de 2016, 2h15 que no se observa en Europa occidental (debido al cambio de horario de verano , el reloj se mueve de 2h00 a 3h00) que es una fuente común de loco.
Para una máxima portabilidad, use la biblioteca de moment.js . El momento llega con más de 80 locales agrupados.
Usando marca de tiempo y desplazamiento UTC:
moment(1459026900000).utcOffset(300).locale(''fr'').format("LLLL") // "dimanche 27 mars 2016 02:15"
Usando una matriz de enteros (tenga en cuenta que en este momento, el mes está basado en 0, al igual que en el objeto JS Date nativo)
moment.utc([2016,3-1,27,2,15]).locale(''fr'').format("LLLL") // "dimanche 27 mars 2016 02:15"
Puede probar esos métodos ejecutando código en las herramientas de desarrollo del navegador en http://momentjs.com/
La parte difícil aquí es usar moment.utc
que crea un objeto de fecha de momento con el indicador UTC, lo que significa que cuando se formatee esa fecha, no se convertirá a la zona horaria del usuario, sino que se mostrará tal como está (y como UTC no se observa DST, no es propenso a error DST).
Futura solución nativa: utilizando el objeto Intl
(Tenga en cuenta que a finales de 2015, esta solución es compatible con Chrome, Firefox, IE11 pero aún no es compatible con Safari 9 )
Usando una matriz de enteros:
new Intl.DateTimeFormat(''fr-FR'', { timeZone: ''UTC'', weekday: ''long'',
month: ''long'', year: ''numeric'', day: ''numeric'', hour: ''numeric'',
minute: ''numeric'' })
.format(Date.UTC(2016,3-1,27,2,15))
// "dimanche 27 mars 2016 02:15"
La clave aquí es, una vez más, utilizar Date.UTC
y timeZone: ''UTC''
para asegurarse de que la fecha proporcionada no se convertirá a la zona horaria local del usuario.
Tenga en cuenta que en ambos casos estamos usando métodos UTC, solo para asegurarnos de que la fecha se usará como está sin conversiones. Sin embargo, es importante darse cuenta de que esas fechas son fechas UTC falsas (representan el tiempo en una zona horaria arbitraria determinada, no hora UTC), y se deben usar solo para formatear y mostrar la fecha; no se deben pasar por alto.
tiene el mismo problema # 1 es la solución, supongo. Debe enviar todos los componentes de fecha (año, mes, día, horas) en un contenedor especial del cliente al servidor