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



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


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 .


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


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)


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

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()));

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 .


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?


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.