obtener la zona horaria del cliente desde el navegador

139

¿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.

Detección automática de una zona horaria con JavaScript

Detección de zona horaria en JavaScript

Confucio
fuente
8
Escribí jsTimezoneDetect al que se enlaza anteriormente, y mi opinión sobre la situación es que es lo más cercano que puede obtener con javascript cruzado puro (sin geolocalización y búsquedas de IP).
Jon Nylander

Respuestas:

87

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

Ciudadano georgiano
fuente
13
TL; DR Ahora podemos usar Intl.DateTimeFormat().resolvedOptions().timeZone(no IE11) como lo sugiere Wallace.
Code4R7
195

¡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 .

Wallace
fuente
44
no funciona en firefox: Intl.DateTimeFormat().resolvedOptions().timeZone->undefined
Tomas Tomecek
3
Firefox e IE parecen no admitir la propiedad :( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Wallace
55
Intl.DateTimeFormat().resolvedOptions().timeZonedevolverá el valor esperado a partir de Firefox 52: kangax.github.io/compat-table/esintl/…
julen
¿Cómo se usa este es un formulario? ¿En un valor oculto como se sugiere en developer.mozilla.org/en-US/docs/Web/HTML/Element/input/… ?
hendry
44
Ahora funciona en Firefox
Dustin Michels
76

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).

Chris W.
fuente
30
Vale la pena señalar que el desplazamiento y la zona horaria no son necesariamente lo mismo.
Dex
9
¿Cómo aplicaría DST solo con el desplazamiento? En esas áreas, la compensación es incorrecta la mitad del año. OMI, la zona horaria es más precisa.
Savageman
44
El horario de verano es parte del desplazamiento en un momento dado. La hora de Europa Central en invierno es UTC + 01: 00. Sin embargo, cuando se aplica DST, CET es UTC + 02: 00, como ahora en Dinamarca, donde estoy.
Gert Sønderby
1
esta es la razón por la cual getTimezoneOffset () necesita una fecha para trabajar: agregará el horario de verano vigente en ese momento.
OsamaBinLogin
2
la compensación no es precisa cuando se considera el horario de verano.
Greg L.
48

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)

Johannes Hoff
fuente
1
Intl se ve estable en todo menos en Safari. caniuse.com/#feat=internationalization
Michael Cole
2
@MichaelCole Se supone que las implementaciones conformes de Intldevuelven undefinedpara la timeZonepropiedad 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".
Chris Jester-Young
20
FYI - el estándar ahora es Intl.DateTimeFormat (). ResolveOptions (). TimeZone
Nederby
4

podrías usar moment-timezone para adivinar la zona horaria:

> moment.tz.guess()
"America/Asuncion"
Tomás Tomecek
fuente
4

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()));
Pushkar Newaskar
fuente
1
Para mostrar la fecha como 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()));
αƞjiβ
55
Su violín ya no funciona y está dando errores en la consola.
Saumil
2

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.UTCoffsetTal desplazamiento en la forma '±hhmmD'(por ejemplo, '-0600D'), donde el sufijo es Dpara DST y Spara estándar (no DST);
  • ClientTZ.hasDST (a verdadero o falso).

Se ClientTZ.UTCoffsetproporciona en minutos en lugar de horas, porque algunas zonas horarias tienen desplazamientos fraccionales por hora (por ejemplo, +0415).

La intención detrás ClientTZ.UTCoffsetTes usarlo como una clave en una tabla de zonas horarias (no se proporciona aquí), como para una <select>lista desplegable .

David R Tribble
fuente
Parece que siempre devolverá 'D' si se observa el horario de verano. ¿Y por qué solo cinco meses de diferencia? ¿Seguramente, enero y julio funcionarán de manera más confiable?
Matt
@Matt: Sí, puede usar 7-1para 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.
David R Tribble
-13

No. No hay una única forma confiable y nunca la habrá. ¿Realmente pensaste que podías confiar en el cliente?

Florian Margaine
fuente
23
Para aclarar: el reloj del cliente puede no estar configurado correctamente, o pueden estar tratando de engañarlo para que piense que están en una zona horaria diferente de la real. Si va a utilizar la zona horaria del cliente, no lo haga por nada importante.
Ryan Kinal
77
-1 por dar una respuesta potencialmente engañosa y no aclarar.
Doug S
66
Sí, para mi aplicación puedo confiar en el cliente. Si el cliente ha sido mal configurado o tiene un error, eso está en mis usuarios.
Michael Cole
3
De hecho, estoy de acuerdo con Florian. Método confiable? Mas o menos. ¿Datos fiables? Definitivamente no.
Rob
44
La pregunta no dice cómo se usarán los datos. Por ejemplo, no dice que la zona horaria detectada se envíe alguna vez a un servidor. Por lo tanto, la observación sobre la confianza es irrelevante si los datos se usan exclusivamente a nivel local.
dolmen