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.
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.
Respostas:
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
Intl.DateTimeFormat().resolvedOptions().timeZone
(sem IE11), conforme sugerido por Wallace.
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 .
Intl.DateTimeFormat().resolvedOptions().timeZone
->undefined
Intl.DateTimeFormat().resolvedOptions().timeZone
retornará o valor esperado a partir do Firefox 52: kangax.github.io/compat-table/esintl/…
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.)
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)
Intl
devem retornar undefined
para a timeZone
propriedade 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".
você pode usar o fuso horário do momento para adivinhar o fuso horário:
> moment.tz.guess()
"America/Asuncion"
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()));
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()));
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.UTCoffsetT
para o deslocamento na forma '±hhmmD'
(por exemplo, '-0600D'
), onde o sufixo é D
para DST e S
para 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 .
7-1
para 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.
Não. Não existe uma maneira única e confiável e nunca haverá. Você realmente achou que podia confiar no cliente?