Obtendo deslocamento do fuso horário do cliente em JavaScript

615

Como posso coletar informações de fuso horário do visitante? Preciso do fuso horário e das horas de deslocamento GMT.

Controlaríztűrő tükörfúrógép
fonte
3
Estou enfrentando o mesmo problema agora. Aqui está uma abordagem interessante.
Tamás Pap
31
O título solicita o fuso horário, enquanto o texto solicita o deslocamento GMT. Estas são duas coisas diferentes. Um fuso horário inclui informações sobre o horário de verão, o deslocamento utc não. Um fuso horário tem um nome e histórico, o deslocamento não. Recomenda-se editar o título para "Obtendo o deslocamento gmt do cliente em JS".
Citykid
Eu preciso do fuso horário. A compensação GMT também seria útil.
#
9
As respostas aqui se concentram principalmente no deslocamento . Para o fuso horário, veja esta resposta . Consulte "Fuso horário! = Deslocamento" no wiki da tag de fuso horário .
Matt Johnson-Pint
7
Você começa Fuso horário exata usando este Intl.DateTimeFormat () timeZone resolvedOptions ()..
Mangesh Mandavgane

Respostas:

594

var offset = new Date().getTimezoneOffset();
console.log(offset);

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, se o seu fuso horário for UTC + 10 (Horário Padrão do Leste da Austrália), -600 será retornado. O horário de verão impede que esse valor seja constante, mesmo para um determinado local

Observe que nem todos os fusos horários são compensados ​​por horas inteiras: por exemplo, Terra Nova é UTC menos 3h 30m (deixando o Horário de verão fora da equação).

NickFitz
fonte
42
@abernier A declaração sobre getTimezoneOffsetimprecisão está em vigor? O artigo a que você está se referindo é datado de junho de 2007 e não possui detalhes de como a função é imprecisa. E, de fato, a biblioteca que jsTimezoneDetectvocê apontou se usa getTimezoneOffset.
Mike
5
@ abernier É um padrão desde o ES 1, por isso tenho certeza de que qualquer problema de implementação pode estar resolvido agora, quero dizer, que é um artigo de 7 anos.
LasagnaAndroid
49
var hrs = -(new Date().getTimezoneOffset() / 60) para se compensar em horas tipicamente usado
Edwin Daniels
6
Parece que não se considera a hora de Verão
Shahdat
21
timezone! =utc offset
bendytree
483

Usar um deslocamento para calcular o fuso horário é uma abordagem incorreta e você sempre encontrará problemas. Os fusos horários e as regras de horário de verão podem mudar em várias ocasiões durante um ano, e é difícil acompanhar as alterações.

Para obter o fuso horário da IANA do sistema em JavaScript, você deve usar

console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)

Em setembro de 2019, isso funcionaria em 95% dos navegadores usados ​​globalmente .

Informações antigas de compatibilidade

O ecma-402 / 1.0 diz que timeZonepode ser indefinido se não for fornecido ao construtor. No entanto, o rascunho futuro (3.0) corrigiu esse problema alterando para o fuso horário padrão do sistema.

Nesta versão da API de internacionalização do ECMAScript, a timeZonepropriedade permanecerá indefinida se nenhuma timeZonepropriedade foi fornecida no objeto de opções fornecido ao Intl.DateTimeFormat construtor . No entanto, os aplicativos não devem confiar nisso, pois versões futuras podem retornar um valor String identificando o fuso horário atual do ambiente host.

no ecma-402 / 3.0, que ainda está em rascunho, foi alterado para

Nesta versão da API de internacionalização do ECMAScript 2015, a timeZonepropriedade será o nome do fuso horário padrão se nenhuma timeZonepropriedade tiver sido fornecida no objeto de opções fornecido ao Intl.DateTimeFormatconstrutor. A versão anterior deixou a timeZonepropriedade indefinida neste caso.

Pawel Dubiel
fonte
17
Essa é a única resposta para obter o fuso horário, que alguns usuários podem precisar, em vez de apenas o deslocamento. Portanto, como uma atualização em 2016-09, o Intl funciona nos navegadores mais modernos, mas não no Safari. Para esse navegador, há um fallback de javascript razoavelmente preciso aqui - pellepim.bitbucket.org/jstz
user2085368
6
Verificou que agora parece funcionar no Safari. (Usando a versão 10.0)
BadPirate 19/10/16
2
Seria bom se isso funcionasse em todos os navegadores modernos. No entanto, o IE11 e o Firefox mais recente retornam indefinidos para a propriedade timeZone.
Haprog
7
Eu testei agora com o Chrome 58, Edge 40 e Firefox 53 - ele funciona com todos eles. Não funciona com o IE 11, não testei o Opera.
Suma
8
Demorei um pouco para encontrar a lista de fusos horários retornados por esta API. Aqui está: en.wikipedia.org/wiki/List_of_tz_database_time_zones
Xavier Poinas
123

Sei que essa resposta é um pouco fora do tópico, mas imagino que muitos de nós procurando uma resposta também queriam formatar o fuso horário para exibição e talvez também obter a abreviação de zona. Então aqui vai ...

Se você deseja que o fuso horário do cliente seja bem formatado, pode confiar no método JavaScript Date.toString e fazer:

var split = new Date().toString().split(" ");
var timeZoneFormatted = split[split.length - 2] + " " + split[split.length - 1];

Isso fornecerá "GMT-0400 (EST)", por exemplo, incluindo os minutos do fuso horário, quando aplicável.

Como alternativa, com o regex, você pode extrair qualquer parte desejada:

Para "GMT-0400 (EDT)":

new Date().toString().match(/([A-Z]+[\+-][0-9]+.*)/)[1]

Para "GMT-0400":

new Date().toString().match(/([A-Z]+[\+-][0-9]+)/)[1]

Por apenas "EDT":

new Date().toString().match(/\(([A-Za-z\s].*)\)/)[1]

Por apenas "-0400":

new Date().toString().match(/([-\+][0-9]+)\s/)[1]

Referência de Date.toString: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toString

Marquez
fonte
4
Quebrado com o Chrome, pois acrescenta o nome do fuso horário. Não use split.length, mas uma constante split[4] + " " + split[5]?!
Christophe Roussy
4
Isso também não funciona (surpresa, surpresa) no IE. Acabei de fazer um despejo de console do objeto Date dividido. É o mesmo no Chrome, Firefox e Safari, mas diferente no IE. Portanto, você também não pode contar com os índices constantes. Seg 02 de dezembro de 2013 10:22:50 GMT-0500 (EST): Chrome, FF, Safari; Seg 2 Dez 10:22:50 EST 2013: IE10
adimauro
1
Puxa, obrigado! Eu estive pulando através de argolas tentando exibir o fuso horário do navegador ..... ew Date (). ToString (). Match (/ ([AZ] + [\ + -] [0-9] +. *) /) [ 1] era exatamente o que eu precisava!
KiwiSunGoddess
1
Isso não funciona. Para mim, splitcontém: ["Mon", "Mar", "13", "2017", "14:05:22", "GMT-0400", "(Eastern", "Daylight", "Time)"]então o resultado é #Daylight Time)
DLeh 13/0317
7
Na verdade, não é uma boa ideia que a representação real do tempo de JS depois que você o faça new Date().toString()depende completamente das configurações de localidade. Esperar que os resultados de outros clientes se assemelhem aos seus é uma péssima idéia.
Octopus
71

Já foi respondido como obter o deslocamento em minutos como um número inteiro, mas caso alguém queira o deslocamento GMT local como uma sequência, por exemplo "+1130":

function pad(number, length){
    var str = "" + number
    while (str.length < length) {
        str = '0'+str
    }
    return str
}

var offset = new Date().getTimezoneOffset()
offset = ((offset<0? '+':'-')+ // Note the reversed sign!
          pad(parseInt(Math.abs(offset/60)), 2)+
          pad(Math.abs(offset%60), 2))
crio
fonte
1
Você precisa substituir o primeiro preenchimento por pad(parseInt(Math.abs(offset/60)), 2)para acertar ... caso contrário, você poderá obter +5.530, como no meu caso ... não tenho certeza se o piso de matemática etc. será uma coisa melhor aqui ou não ... mas isso pelo menos me dá +530 conforme o esperado
Abhinav Singh
Exatamente o que eu tenho procurado. Obrigado !
codesnooker
isso dará o resultado correto: this.pad (Math.floor ((Math.abs (offset / 60))), 2)
Vivek
Em vez de usar a função pad, acho mais fácil fazer isso: offset = (offset <0? "+": "-") + ("0000" + parseInt ((Math.abs (offset / 60)))) .slice (-4)
flurbius 5/17
67

Você pode usar:

fuso horário

<script src="moment.js"></script>
<script src="moment-timezone-with-data.js"></script>

// retrieve timezone by name (i.e. "America/Chicago")
moment.tz.guess();

A detecção do fuso horário do navegador é bastante complicada de corrigir, pois há pouca informação fornecida pelo navegador.

Momento O fuso horário usa Date.getTimezoneOffset()e Date.toString()em alguns momentos do ano atual para reunir o máximo de informações possível sobre o ambiente do navegador. Em seguida, compara essas informações com todos os dados de fuso horário carregados e retorna a correspondência mais próxima. Em caso de empate, o fuso horário da cidade com maior população é retornado.

console.log(moment.tz.guess()); // America/Chicago
Sameer Ek
fonte
12
Essa deve ser a resposta aceita. Este é o único que fornece o nome real do fuso horário, em vez de deslocamento. Lembre-se de que o deslocamento do fuso horário pode ser derivado do nome, o contrário não é verdadeiro. Devido ao horário de verão e outras sutilezas, vários fusos horários podem ter o mesmo deslocamento em apenas alguns dias específicos do ano.
Romain L
1
Há uma solução nativa para isso agora - a API Intl . Embora o moment.js tenha sido uma ótima biblioteca, existem alternativas muito menores atualmente ( dayjs , date-fns ). O momento é enorme ; não o recomende para aplicativos clientes.
Dan Dascalescu 17/03/19
43

Eu escrevi uma função no meu projeto, que retorna o fuso horário no hh:mmformato. Espero que isso ajude alguém:

function getTimeZone() {
    var offset = new Date().getTimezoneOffset(), o = Math.abs(offset);
    return (offset < 0 ? "+" : "-") + ("00" + Math.floor(o / 60)).slice(-2) + ":" + ("00" + (o % 60)).slice(-2);
}

// Outputs: +5:00

Violino de trabalho

Senhor Verde
fonte
1
Obrigado! Era disso que eu precisava!
Jeremy Moritz
15

Uma linha única que fornece o deslocamento e o fuso horário é simplesmente chamar toTimeString () em um novo objeto Date. Do MDN:

O toTimeString()método retorna a parte da hora de um objeto Date em formato legível por humanos no inglês americano.

O problema é que o fuso horário não está no formato padrão da IANA; é um pouco mais amigável do que o formato IANA "continente / cidade" . Experimente:

console.log(new Date().toTimeString().slice(9));
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
console.log(new Date().getTimezoneOffset() / -60);

No momento, na Califórnia, toTimeString()retorna Pacific Daylight Timeenquanto a API Intl retorna America/Los_Angeles. Na Colômbia, que você deseja obter Colombia Standard Time, vs. America/Bogota.

Observe que muitas outras respostas para esta pergunta tentam obter as mesmas informações chamando Date.toString (). Essa abordagem não é tão confiável, como a MDN explica :

As instâncias de data se referem a um momento específico. Chamar toString () retornará a data formatada em um formato legível por humanos no inglês americano. [...] Às vezes é desejável obter uma sequência da parte do tempo; uma coisa dessas pode ser realizada com o toTimeString()método

O toTimeString()método é especialmente útil porque os mecanismos compatíveis que implementam o ECMA-262 podem diferir na sequência obtida toString()para os Dateobjetos, pois o formato depende da implementação; abordagens simples de corte de cadeia podem não produzir resultados consistentes em vários mecanismos.

Dan Dascalescu
fonte
13

tentativa getTimezoneOffset()do Dateobjeto:

var curdate = new Date()
var offset = curdate.getTimezoneOffset()

Esse método retorna o deslocamento do fuso horário em minutos, que é a diferença entre GMT e o horário local em minutos.

dfa
fonte
9

JavaScript:

var d = new Date();
var n = d.getTimezoneOffset();
var timezone = n / -60;
console.log(timezone);

زي
fonte
3
O que essa resposta fornece que as respostas anteriores não forneceram?
Dan Dascalescu 17/03/19
7

Com moment.js :

moment().format('zz');
Kolypto
fonte
6
ze zzfoi descontinuado a partir da versão
MrUpsidown
3
@MrUpsidown agora ZeZZ
brauliobo
4
@brauliobo Esses parâmetros não retornam a mesma coisa. z e zz retornaram o fuso horário, por exemplo, CST, mas Z e ZZ retornam o deslocamento, por exemplo, -0600.
Luca Spiller #
Os documentos mais recentes mostram .zoneAbbr()foi substituído ze zz. Veja a documentação aqui
tabish89
1
Embora o moment.js tenha sido uma ótima biblioteca, existem alternativas muito menores atualmente ( dayjs , date-fns ). O momento é enorme ; não o recomende para aplicativos clientes.
Dan Dascalescu 17/03/19
6

Com , você pode encontrar o fuso horário atual como

console.log(moment().utcOffset()); // (-240, -120, -60, 0, 60, 120, 240, etc.)
<script src="https://cdn.jsdelivr.net/momentjs/2.13.0/moment.min.js"></script>


Com , você pode encontrar o fuso horário atual como

console.log(dayjs().utcOffset()); // (-240, -120, -60, 0, 60, 120, 240, etc.)
<script src="https://unpkg.com/[email protected]/dayjs.min.js"></script>

A API retorna o deslocamento utc em minutos.

Fizer Khan
fonte
Embora o moment.js tenha sido uma ótima biblioteca, existem alternativas muito menores atualmente ( dayjs , date-fns ). O momento é enorme ; não o recomende para aplicativos clientes.
Dan Dascalescu 17/03/19
1
"Com o dayjs, você pode encontrar o fuso horário atual como" não é exatamente preciso - você encontrará apenas o deslocamento, não o fuso horário . Além disso, o Dayjs não tem suporte para fuso horário . Seu método .utcOffset () é um invólucro simples sobre o nativo getTimezoneOffset().
Dan Dascalescu 20/03/19
4

Fuso horário em horas-

var offset = new Date().getTimezoneOffset();
if(offset<0)
    console.log( "Your timezone is- GMT+" + (offset/-60));
else
    console.log( "Your timezone is- GMT-" + offset/60);

Se você quiser ser preciso, como mencionado no comentário, tente o seguinte:

var offset = new Date().getTimezoneOffset();

if(offset<0)
{
    var extraZero = "";
    if(-offset%60<10)
      extraZero="0";

    console.log( "Your timezone is- GMT+" + Math.ceil(offset/-60)+":"+extraZero+(-offset%60));
}
else
{
    var extraZero = "";
    if(offset%60<10)
      extraZero="0";

    console.log( "Your timezone is- GMT-" + Math.floor(offset/60)+":"+extraZero+(offset%60));
}

Abrar Jahin
fonte
Não funciona para fusos horários quando não é uma hora inteira, como a Venezuela, onde ele retornar GMT-4,5
Mirko
Sim isso está certo. 0,5 significa 0,5 * 30 minutos. Eu acho que você entendeu isso porque está dando 0,5?
Abrar Jahin 27/03
sim, portanto, o GMT-4.5 não é um fuso horário válido, ele precisa de um pouco de análise extra para se tornar GMT-4: 30
Mirko
@Mirko agora a segunda parte da resposta é para você
Abrar Jahin 27/03
Se você quiser ser mais preciso, use o UTC em vez do GMT, [Hilton e McCarthy 2013, p. 231-2. ], veja também na wikipedia GMT - ( en.wikipedia.org/wiki/Greenwich_Mean_Time )
Tom Kuschel
3

Se tudo o que você precisa é da abreviação de fuso horário "MST" ou "EST":

function getTimeZone(){
    var now = new Date().toString();
    var timeZone = now.replace(/.*[(](.*)[)].*/,'$1');//extracts the content between parenthesis
    return timeZone;
}
JohnP2
fonte
O uso Date.toString()não é confiável e o MDN explica o porquê. Colei a seção relevante dos documentos deles na minha resposta .
Dan Dascalescu 17/03/19
3

Veja que este operador resultante era oposto ao fuso horário. Portanto, aplique alguma função matemática e valide o número menor ou mais.

insira a descrição da imagem aqui

Veja o documento MDN

var a = new Date().getTimezoneOffset();

var res = -Math.round(a/60)+':'+-(a%60);
res = res < 0 ?res : '+'+res;

console.log(res)

prasanth
fonte
1
Revestir de valor negativo, algum problema
Arun Prasad ES
1
Por que round? Deveria ser floor, não é?
21418 Qwertiy
3
function getLocalTimeZone() {
    var dd = new Date();
    var ddStr = dd.toString();
    var ddArr = ddStr.split(' ');
    var tmznSTr = ddArr[5];
    tmznSTr = tmznSTr.substring(3, tmznSTr.length);
    return tmznSTr;
}

Exemplo: quinta-feira 21 de junho de 2018 18:12:50 GMT + 0530 (horário padrão da Índia)

O / P: +0530

Chandrakanth Gowda
fonte
O uso Date.toString()não é confiável e o MDN explica o porquê. Colei a seção relevante dos documentos deles na minha resposta .
Dan Dascalescu 17/03/19
3

Tente isso,

new Date().toString().split("GMT")[1].split(" (")[0]
Srinivasan Sekar
fonte
2

Esse valor é da máquina do usuário e pode ser alterado a qualquer momento, por isso acho que não importa, só quero obter um valor aproximado e depois convertê-lo em GMT no meu servidor.

Por exemplo, sou de Taiwan e retorna "+8" para mim.

Exemplo de trabalho

JS

function timezone() {
    var offset = new Date().getTimezoneOffset();
    var minutes = Math.abs(offset);
    var hours = Math.floor(minutes / 60);
    var prefix = offset < 0 ? "+" : "-";
    return prefix+hours;
}


$('#result').html(timezone());

HTML

<div id="result"></div>

Resultado

+8
Terry Lin
fonte
2

No new Date() você pode obter o deslocamento, para obter o nome do fuso horário que você pode fazer:

new Date().toString().replace(/(.*\((.*)\).*)/, '$2');

você obtém o valor ()no final da data, que é o nome do fuso horário.

Moysés Lacerda
fonte
O uso Date.toString()não é confiável e o MDN explica o porquê. Colei a seção relevante dos documentos deles na minha resposta . Além disso, esta resposta já foi dada pelo menos três vezes.
Dan Dascalescu 17/03/19
2

Esta seria a minha solução:


    // For time zone:
    const timeZone = /\((.*)\)/.exec(new Date().toString())[1];
    
    // Offset hours:
    const offsetHours = new Date().getTimezoneOffset() / 60;
    
    console.log(`${timeZone}, ${offsetHours}hrs`);

fonte
1

Como alternativa new Date().getTimezoneOffset()e moment().format('zz'), você também pode usar:

var offset = moment.parseZone(Date.now()).utcOffset() / 60
console.log(offset);
<script src="https://cdn.jsdelivr.net/momentjs/2.13.0/moment.min.js"></script>

O jstimezone também é bastante complicado e não mantém manutenção ( https://bitbucket.org/pellepim/jstimezonedetect/issues?status=new&status=open )

brauliobo
fonte
Embora o moment.js tenha sido uma ótima biblioteca, existem alternativas muito menores atualmente ( dayjs , date-fns ). O momento é enorme ; não o recomende para aplicativos clientes.
Dan Dascalescu 17/03/19
1

Use isto para converter OffSet em positivo:

var offset = new Date().getTimezoneOffset();
console.log(offset);
this.timeOffSet = offset + (-2*offset);
console.log(this.timeOffSet);
Kumal Pereira
fonte
-2

Eu estava procurando apenas a sequência de três letras (como "PDT") e tentei a resposta de Marquez, mas tive que ajustá-la um pouco para obter suporte entre navegadores. Felizmente, a string é a última correspondência potencial :)

Aqui está o que eu fiz, no CoffeeScript:

browserTimezone = ->
  userDate = new Date()
  zoneMatches = userDate.toString().match(/([A-Z][A-Z][A-Z])/g)
  userZone = zoneMatches[zoneMatches.length - 1]

Funciona no IE8, IE9, Safari 9, Firefox 44 e Chrome 48

ari gold
fonte
2
Há fusos horários com 4 letras embora - tenha cuidado: CEST por exemplo (Horário de Verão da Europa Central)
jbrosi
O uso Date.toString()não é confiável e o MDN explica o porquê. Colei a seção relevante dos documentos deles na minha resposta .
Dan Dascalescu 17/03/19
-3

Você apenas inclui moment.js e jstz.js

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.6/jstz.min.js"></script>

e depois disso

<script>
$(function(){
 var currentTimezone = jstz.determine();
 var timezone = currentTimezone.name();
 alert(timezone);
});

</script>
Dayachand Patel
fonte
-3

Este é um trabalho muito bom para mim:

// Translation to offset in Unix Timestamp
let timeZoneOffset = ((new Date().getTimezoneOffset())/60)*3600;
Alexander
fonte
1
Alguma explicação?
-4

você pode simplesmente tentar isso. ele retornará o tempo atual da máquina

var _d = new Date(), t = 0, d = new Date(t*1000 + _d.getTime())

user8066707
fonte
É assim que deve ser feito, penso: new Date(new Date().getTime()); seria exibido: "Sex 28 de dezembro de 2018 10:15:23 GMT + 0100 (Horário padrão da Europa Central) {}"
darmis
-4

Isso fará o trabalho.


var time = new Date(),
timestamp = Date(1000 + time.getTime());
console.log(timestamp);

Thu May 25 2017 21:35:14 GMT+0300 (IDT)

Indefinido

SysMurff
fonte