obter fuso horário do cliente no navegador


138

Existe uma maneira confiável de obter um fuso horário no navegador do cliente? Vi os links a seguir, mas quero uma solução mais robusta.

Detectar automaticamente um fuso horário com JavaScript

Detecção de fuso horário em JavaScript



8
Eu escrevi para o jsTimezoneDetect que você vincula acima, e minha opinião é que ela é o mais próximo possível do javascript puro entre navegadores (sem geolocalização e pesquisas de IP).
Jon Nylander

Respostas:


87

Olhe para este pageloom de repositório , é útil

faça o download do jstz.min.js e adicione uma função à sua página html

<script language="javascript">
    function getTimezoneName() {
        timezone = jstz.determine()
        return timezone.name();
    }
</script>

e chame essa função da sua tag de exibição


13
TL; DR Agora, podemos usar Intl.DateTimeFormat().resolvedOptions().timeZone(sem IE11), conforme sugerido por Wallace.
Code4R7

194

Meia década depois, temos um caminho embutido para isso! Para navegadores modernos, eu usaria:

const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);

Isso retorna uma sequência de fuso horário da IANA, mas não o deslocamento . Saiba mais na referência MDN .

Tabela de compatibilidade - a partir de março de 2019, funciona para 90% dos navegadores usados ​​globalmente. Não funciona no Internet Explorer .


4
não funciona no firefox: Intl.DateTimeFormat().resolvedOptions().timeZone->undefined
Tomas Tomecek 6/16

3
O Firefox e o IE parecem não suportar a propriedade :( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Wallace

5
Intl.DateTimeFormat().resolvedOptions().timeZoneretornará o valor esperado a partir do Firefox 52: kangax.github.io/compat-table/esintl/…
julen

Como alguém usa esse formulário? Em um valor oculto, conforme sugerido em developer.mozilla.org/en-US/docs/Web/HTML/Element/input/… ?
hendry

4
Funciona agora no Firefox
Dustin Michels

74

Frequentemente, quando as pessoas procuram "fusos horários", basta apenas "deslocamento UTC". por exemplo, o servidor deles está no UTC + 5 e eles querem saber que o cliente está executando no UTC-8 .


No javascript antigo simples (new Date()).getTimezoneOffset()/60 retornará o número atual de horas deslocadas do UTC.

Vale a pena notar uma possível "pegadinha" no sinal do getTimezoneOffset()valor de retorno (dos documentos MDN) :

O deslocamento do fuso horário é a diferença, em minutos, entre o UTC e a hora local. Observe que isso significa que o deslocamento é positivo se o fuso horário local estiver atrás do UTC e negativo se estiver adiantado. Por exemplo, para o fuso horário UTC + 10: 00 (Horário Padrão do Leste da Austrália, Horário Vladivostok, Horário Padrão de Chamorro), -600 será retornado.


No entanto, recomendo que você use o day.js para código Javascript relacionado a hora / data. Nesse caso, você pode obter um deslocamento UTC formatado ISO 8601 executando:

> dayjs().format("Z")
"-08:00"

Provavelmente vale mencionar que o cliente pode facilmente falsificar essas informações.

(Nota: esta resposta foi originalmente recomendada https://momentjs.com/ , mas o dayjs é uma alternativa mais moderna e menor.)


30
Pode-se notar que deslocamento e fuso horário não são necessariamente a mesma coisa.
Dex

9
Como você aplicaria o horário de verão apenas com o deslocamento? Nessas áreas, o deslocamento está errado na metade do ano. OMI, o fuso horário é mais preciso.
Savageman

4
O horário de verão faz parte do deslocamento a qualquer momento. O horário da Europa Central no inverno é UTC + 01: 00. No entanto, quando o horário de verão é aplicado, o CET é UTC + 02: 00, como agora na Dinamarca, onde estou.
Gert Sønderby

1
é por isso que getTimezoneOffset () precisa de uma data para trabalhar - ele adicionará o horário de verão em vigor naquele momento.
OsamaBinLogin

2
o deslocamento não é preciso ao considerar o horário de verão.
Greg L.

48

Por enquanto, a melhor aposta é provavelmente jstz, como sugerido na resposta de mbayloon .

Para completar, deve-se mencionar que existe um padrão no caminho: Intl . Você já pode ver isso no Chrome:

> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"

(Na verdade, isso não segue o padrão, que é mais um motivo para permanecer na biblioteca)


1
O Intl parece estável em tudo, menos no Safari. caniuse.com/#feat=internationalization
Michael Cole

2
As implementações do @MichaelCole ConformantIntl devem retornar undefinedpara a timeZonepropriedade se você não especificou manualmente um fuso horário na construção do DateTimeFormat. O Chrome se desvia do padrão retornando o fuso horário do sistema; é isso que a resposta de Johannes explora, mas também porque ele disse que "realmente não segue o padrão".
Chris Jester-Young

19
FYI - o padrão agora é Intl.DateTimeFormat (). ResolvedOptions (). TimeZone
Nederby


4

Aqui está um jsfiddle

Ele fornece a abreviação do fuso horário do usuário atual.

Aqui está o exemplo de código

var tz = jstz.determine();
console.log(tz.name());
console.log(moment.tz.zone(tz.name()).abbr(new Date().getTime()));

1
Para exibir a data como May 22 2015 03:45 PM CDT eu usei console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
αƞjiβ

5
Seu violino não está mais funcionando e está apresentando erros no console.
Saumil 10/11/16

2

Usei uma abordagem semelhante à adotada por Josh Fraser , que determina o tempo de deslocamento do navegador em relação ao UTC e se ele reconhece o horário de verão ou não (mas um pouco simplificado de seu 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();

Ao carregar, a ClientTZ.getBrowserTZ()função é executada, que define:

  • ClientTZ.UTCoffset para o deslocamento da hora do navegador em relação ao UTC em minutos (por exemplo, CST é -360 minutos, ou seja, 6,0 horas em relação ao UTC);
  • ClientTZ.UTCoffsetTpara o deslocamento na forma '±hhmmD'(por exemplo, '-0600D'), onde o sufixo é Dpara DST e Spara padrão (não DST);
  • ClientTZ.hasDST (verdadeiro ou falso).

Ele ClientTZ.UTCoffseté fornecido em minutos, em vez de horas, porque alguns fusos horários têm desvios horários fracionários (por exemplo, +0415).

A intenção por trás disso ClientTZ.UTCoffsetTé usá-lo como uma chave em uma tabela de fusos horários (não fornecida aqui), como em uma <select>lista suspensa .


Parece que sempre retornará 'D' se observar o horário de verão. E por que apenas cinco meses de diferença? Certamente, janeiro e julho funcionarão de maneira mais confiável?
Matt

@ Matt - Sim, você poderia usar 7-1para julho em vez de junho. Não tenho certeza se isso realmente faz alguma diferença, pois duvido que existam esquemas regionais de horário de verão que não incluam junho.
David R Tribble

-13

Não. Não existe uma maneira única e confiável e nunca haverá. Você realmente achou que podia confiar no cliente?


23
Para esclarecer: O relógio do cliente pode não estar ajustado corretamente ou ele pode estar tentando enganá-lo maliciosamente, pensando que eles estão em um fuso horário diferente do real. Se você usar o fuso horário do cliente, não faça isso por nada importante.
Ryan Kinal

7
-1 por dar uma resposta potencialmente enganosa e não esclarecer.
Doug S

6
Sim, para meu aplicativo, posso confiar no cliente. Se o cliente tiver sido configurado incorretamente ou tiver um bug, isso é dos meus usuários.
Michael Cole

3
Na verdade, eu concordo com Florian. Método confiável? Mais ou menos. Dados confiáveis? Definitivamente não.
Rob

4
A questão não diz como os dados serão usados. Por exemplo, não diz que o fuso horário detectado será enviado a um servidor. Portanto, a observação sobre confiança é irrelevante se os dados forem usados ​​exclusivamente localmente.
dólmen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.