¿Hay alguna forma confiable de obtener una zona horaria desde el navegador del cliente? Vi los siguientes enlaces pero quiero una solución más robusta.
¿Hay alguna forma confiable de obtener una zona horaria desde el navegador del cliente? Vi los siguientes enlaces pero quiero una solución más robusta.
Respuestas:
Mire este repositorio pageloom es útil
descargue jstz.min.js y agregue una función a su página html
<script language="javascript">
function getTimezoneName() {
timezone = jstz.determine()
return timezone.name();
}
</script>
y llame a esta función desde su etiqueta de pantalla
Intl.DateTimeFormat().resolvedOptions().timeZone
(no IE11) como lo sugiere Wallace.
¡Media década después tenemos una forma integrada de hacerlo! Para los navegadores modernos usaría:
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);
Esto devuelve una cadena de zona horaria de IANA, pero no el desplazamiento . Obtenga más información en la referencia de MDN .
Tabla de compatibilidad : a partir de marzo de 2019, funciona para el 90% de los navegadores en uso a nivel mundial. No funciona en Internet Explorer .
Intl.DateTimeFormat().resolvedOptions().timeZone
->undefined
Intl.DateTimeFormat().resolvedOptions().timeZone
devolverá el valor esperado a partir de Firefox 52: kangax.github.io/compat-table/esintl/…
A menudo, cuando las personas buscan "zonas horarias", lo que bastará es simplemente "compensación UTC". por ejemplo, su servidor está en UTC + 5 y quieren saber que su cliente se está ejecutando en UTC-8 .
En javascript antiguo (new Date()).getTimezoneOffset()/60
, devolverá el número actual de horas compensadas desde UTC.
Vale la pena señalar un posible "problema" en el signo del getTimezoneOffset()
valor de retorno (de los documentos MDN) :
El desplazamiento de zona horaria es la diferencia, en minutos, entre la hora UTC y la hora local. Tenga en cuenta que esto significa que el desplazamiento es positivo si la zona horaria local está detrás de UTC y negativo si está adelante. Por ejemplo, para la zona horaria UTC + 10: 00 (hora estándar del este de Australia, hora de Vladivostok, hora estándar de Chamorro), se devolverá -600.
Sin embargo, le recomiendo que use day.js para el código Javascript relacionado con la hora / fecha. En ese caso, puede obtener un desplazamiento UTC formateado con ISO 8601 ejecutando:
> dayjs().format("Z")
"-08:00"
Probablemente vale la pena mencionar que el cliente puede falsificar fácilmente esta información.
(Nota: esta respuesta originalmente recomendaba https://momentjs.com/ , pero dayjs es una alternativa más moderna y más pequeña).
Por ahora, la mejor apuesta es probablemente jstz como se sugiere en la respuesta de mbayloon .
Para completar, debe mencionarse que hay un estándar en camino: Intl . Ya puedes ver esto en Chrome:
> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"
(Esto en realidad no sigue el estándar, que es una razón más para seguir con la biblioteca)
Intl
devuelven undefined
para la timeZone
propiedad si no especificó manualmente una zona horaria en la construcción de DateTimeFormat
. Chrome se desvía del estándar al devolver la zona horaria del sistema; eso es lo que explota la respuesta de Johannes, pero también por qué dijo "en realidad no sigue el estándar".
podrías usar moment-timezone para adivinar la zona horaria:
> moment.tz.guess()
"America/Asuncion"
Aquí hay un jsfiddle
Proporciona la abreviatura de la zona horaria del usuario actual.
Aquí está el ejemplo de código
var tz = jstz.determine();
console.log(tz.name());
console.log(moment.tz.zone(tz.name()).abbr(new Date().getTime()));
May 22 2015 03:45 PM CDT
solía console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
Utilicé un enfoque similar al adoptado por Josh Fraser , que determina el desplazamiento de tiempo del navegador desde UTC y si reconoce DST o no (pero algo simplificado de su código):
var ClientTZ = {
UTCoffset: 0, // Browser time offset from UTC in minutes
UTCoffsetT: '+0000S', // Browser time offset from UTC in '±hhmmD' form
hasDST: false, // Browser time observes DST
// Determine browser's timezone and DST
getBrowserTZ: function () {
var self = ClientTZ;
// Determine UTC time offset
var now = new Date();
var date1 = new Date(now.getFullYear(), 1-1, 1, 0, 0, 0, 0); // Jan
var diff1 = -date1.getTimezoneOffset();
self.UTCoffset = diff1;
// Determine DST use
var date2 = new Date(now.getFullYear(), 6-1, 1, 0, 0, 0, 0); // Jun
var diff2 = -date2.getTimezoneOffset();
if (diff1 != diff2) {
self.hasDST = true;
if (diff1 - diff2 >= 0)
self.UTCoffset = diff2; // East of GMT
}
// Convert UTC offset to ±hhmmD form
diff2 = (diff1 < 0 ? -diff1 : diff1) / 60;
var hr = Math.floor(diff2);
var min = diff2 - hr;
diff2 = hr * 100 + min * 60;
self.UTCoffsetT = (diff1 < 0 ? '-' : '+') + (hr < 10 ? '0' : '') + diff2.toString() + (self.hasDST ? 'D' : 'S');
return self.UTCoffset;
}
};
// Onload
ClientTZ.getBrowserTZ();
Al cargar, ClientTZ.getBrowserTZ()
se ejecuta la función, que establece:
ClientTZ.UTCoffset
al tiempo de desplazamiento del navegador desde UTC en minutos (por ejemplo, CST es -360 minutos, que es -6.0 horas desde UTC);ClientTZ.UTCoffsetT
al desplazamiento en la forma '±hhmmD'
(por ejemplo, '-0600D'
), donde el sufijo es D
para DST y S
para estándar (no DST);ClientTZ.hasDST
(a verdadero o falso).Se ClientTZ.UTCoffset
proporciona en minutos en lugar de horas, porque algunas zonas horarias tienen desplazamientos fraccionales por hora (por ejemplo, +0415).
La intención detrás ClientTZ.UTCoffsetT
es usarlo como una clave en una tabla de zonas horarias (no se proporciona aquí), como para una <select>
lista desplegable .
7-1
para julio en lugar de junio. No estoy seguro de si realmente hace alguna diferencia, ya que dudo que haya esquemas regionales de horario de verano que no incluyan junio.
No. No hay una única forma confiable y nunca la habrá. ¿Realmente pensaste que podías confiar en el cliente?