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

confúcio
fonte
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
1
Possível duplicado de Obtendo fuso horário do cliente em JavaScript
Suma

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

Cidadão da Geórgia
fonte
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 .

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

Chris W.
fonte
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)

Johannes Hoff
fonte
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()));
Pushkar Newaskar
fonte
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 .

David R Tribble
fonte
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?

Florian Margaine
fonte
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