javascript - gettimezoneoffset - moment dst time




Como verificar se o DST(horário de verão) está em vigor e se é o que é o deslocamento? (7)

A biblioteca moment.js fornece um método .isDst() em seus objetos de tempo.

momento # isDST verifica se o momento atual está no horário de verão.

moment([2011, 2, 12]).isDST(); // false, March 12 2011 is not DST
moment([2011, 2, 14]).isDST(); // true, March 14 2011 is DST

Este é um pouco do meu código JS para o qual isso é necessário:

var secDiff = Math.abs(Math.round((utc_date-this.premiere_date)/1000));
this.years = this.calculateUnit(secDiff,(86400*365));
this.days = this.calculateUnit(secDiff-(this.years*(86400*365)),86400);
this.hours = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)),3600);
this.minutes = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)-(this.hours*3600)),60);
this.seconds = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)-(this.hours*3600)-(this.minutes*60)),1);

Eu quero obter o datetime no passado, mas se o DST estiver em uso, as datas serão desativadas em 1 hora. Não sei como verificar se o horário de verão está em uso ou não.

Como posso saber quando o horário de verão começa e termina?


Com base no comentário de Matt Johanson sobre a solução fornecida por Sheldon Griffin, criei o seguinte código:

    Date.prototype.stdTimezoneOffset = function() {
        var fy=this.getFullYear();
        if (!Date.prototype.stdTimezoneOffset.cache.hasOwnProperty(fy)) {

            var maxOffset = new Date(fy, 0, 1).getTimezoneOffset();
            var monthsTestOrder=[6,7,5,8,4,9,3,10,2,11,1];

            for(var mi=0;mi<12;mi++) {
                var offset=new Date(fy, monthsTestOrder[mi], 1).getTimezoneOffset();
                if (offset!=maxOffset) { 
                    maxOffset=Math.max(maxOffset,offset);
                    break;
                }
            }
            Date.prototype.stdTimezoneOffset.cache[fy]=maxOffset;
        }
        return Date.prototype.stdTimezoneOffset.cache[fy];
    };

    Date.prototype.stdTimezoneOffset.cache={};

    Date.prototype.isDST = function() {
        return this.getTimezoneOffset() < this.stdTimezoneOffset(); 
    };

Ele tenta obter o melhor de todos os mundos, levando em conta todos os comentários e respostas sugeridas anteriormente e especificamente:

1) Armazena em cache o resultado por ano de stdTimezoneOffset para que você não precise recalculá-lo ao testar várias datas no mesmo ano.

2) Não pressupõe que o DST (se existir) seja necessariamente em julho, e funcionará mesmo que em algum momento e em algum lugar seja em qualquer mês. No entanto, o desempenho funcionará mais rápido se, de fato, julho (ou quase meses) for realmente DST.

3) Caso pior, irá comparar o getTimezoneOffset do primeiro de cada mês. [e fazer isso uma vez por ano testado].

A suposição que ainda faz é que o período DST é maior que um único mês.

Se alguém quiser remover essa suposição, ele pode mudar o loop para algo mais parecido com o que está na solução fornecida por Aaron Cole - mas eu ainda iria saltar meio ano à frente e sair do circuito quando dois deslocamentos diferentes forem encontrados.]


Descobri que usar a biblioteca .isDst() com alguns dos conceitos descritos aqui (comparando janeiro a junho) funciona muito bem.

Essa função simples retornará se o fuso horário no qual o usuário está observa o horário de verão:

function HasDST() {
    return moment([2017, 1, 1]).isDST() != moment([2017, 6, 1]).isDST();
}

Uma maneira simples de verificar se isso funciona (no Windows) é alterar seu fuso horário para uma zona sem DST, por exemplo, o Arizona retornará false, enquanto EST ou PST retornará true.


Essa resposta é bem semelhante à resposta aceita, mas não substitui o protótipo Date e usa apenas uma chamada de função para verificar se o horário de verão está em vigor, em vez de dois.

A idéia é que, como nenhum país observa o DST que dura 7 meses [1] , em uma área que observa o horário de verão, a compensação do horário UTC em janeiro será diferente da de julho.

Enquanto o horário de verão move os relógios para frente , o JavaScript sempre retorna um valor maior durante o horário padrão. Portanto, obter o deslocamento mínimo entre janeiro e julho obterá o deslocamento do fuso horário durante o horário de verão.

Em seguida, verificamos se o fuso horário das datas é igual a esse valor mínimo. Se for, então estamos no horário de verão; caso contrário, não somos.

A função a seguir usa esse algoritmo. Ele recebe um objeto de data, d , e retorna true se o horário de verão estiver em vigor para essa data e false se não for:

function isDST(d) {
    let jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset();
    let jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset();
    return Math.max(jan, jul) != d.getTimezoneOffset(); 
}

Eu enfrentei esse mesmo problema hoje, mas como a nossa economia de luz do dia começa e para em momentos diferentes dos EUA (pelo menos da minha compreensão), usei uma rota um pouco diferente.

var arr = [];
for (var i = 0; i < 365; i++) {
 var d = new Date();
 d.setDate(i);
 newoffset = d.getTimezoneOffset();
 arr.push(newoffset);
}
DST = Math.min.apply(null, arr);
nonDST = Math.max.apply(null, arr);

Então você simplesmente compara o deslocamento atual do fuso horário com DST e nonDST para ver qual corresponde.


O método getTimezoneOffset() em JavaScript, em um navegador, retorna o número de minutos de deslocamento do fuso horário 00:00. Por exemplo, o fuso horário America / New_York em Daylight Savings (DST) retorna o número 300. 300 minutos é 5 horas de diferença de zero. 300 minutos divididos por 60 minutos é de 5 horas. Cada fuso horário é comparado ao fuso horário zero, +00: 00 / Etc / GMT / horário de Greenwich.

Documento Web do MDN

A próxima coisa que você deve saber é que o deslocamento tem o sinal oposto do fuso horário real.

As informações sobre fusos horários são mantidas pela Autoridade de Atribuição de Números da Internet (iana)

fusos horários iana

Uma tabela bem formatada de fuso horário é fornecida por joda.org

fusos horários do joda-time

+00: 00 ou Etc / GMT é o horário de Greenwich

Todos os fusos horários são compensados ​​de +00: 00 / "Etc / GMT" / horário de Greenwich

O horário de verão é sempre um horário anterior ao horário "regular" no verão. Você ajusta seus relógios de volta no outono. ("Fall Back" slogan para lembrar o que fazer)

Assim, o horário America / New_York em Daylight Savings (inverno) é uma hora antes do horário normal. Então, por exemplo, o que normalmente era 17h da tarde na cidade de Nova York no verão, agora são 4h da América / New_York em Daylight Savings. O nome "America / New_York" time é um nome de fuso horário "Long Format". A costa leste dos EUA normalmente chama seu fuso horário de Eastern Standard Time (EST)

Se você quiser comparar o deslocamento de fuso horário atual com o deslocamento de fuso horário de alguma outra data, você precisa saber que o sinal matemático (+/- "Positivo / Negativo") do deslocamento do fuso horário é o oposto do fuso horário.

Olhe para a tabela de fuso horário em joda.org e encontre o fuso horário para "America / New_York". Ela terá um sinal negativo na frente do Standard Offset.

A terra gira no sentido anti-horário em seu eixo. Uma pessoa observa o nascer do sol em Greenwich e vê o nascer do sol 5 horas antes que alguém na cidade de Nova York veja o nascer do sol. E alguém na costa oeste dos EUA verá o nascer do sol depois que alguém na costa leste dos EUA vir o nascer do sol.

Há uma razão pela qual você precisa saber tudo isso. Para que você possa determinar logicamente se algum código JavaScript está obtendo o status do horário de verão corretamente ou não, sem precisar testar todos os fusos horários em diferentes momentos do ano.

Imagine que é novembro em Nova York e os relógios foram atrasados ​​uma hora. No verão em Nova York, o deslocamento é de 240 minutos ou 4 horas.

Você pode testar isso criando uma data em julho e, em seguida, obtendo o deslocamento.

var July_Date = new Date(2017, 6, 1);
var july_Timezone_OffSet = July_Date.getTimezoneOffset();

console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

O que será impresso no log do console de ferramentas de desenvolvedor do navegador?

Resposta é: 240

Agora, você pode criar uma data em janeiro e ver o que seu navegador retorna para um deslocamento de fuso horário para a temporada de inverno.

var Jan_Date = new Date(2017, 0, 1);//Month is zero indexed - Jan is zero
var jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();

console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)

A resposta é: 300

Obviamente, 300 é maior que 240. Então, o que isso significa? Você deve escrever um código que testa o deslocamento de inverno sendo maior que o deslocamento de verão? Ou o deslocamento de verão menor que o deslocamento de inverno? Se houver uma diferença entre as compensações de fuso horário no verão e no inverno, você poderá considerar que o horário de verão está sendo usado para esse fuso horário. Mas isso não diz se hoje está usando o horário de verão para o fuso horário dos navegadores. Então, você precisa obter o deslocamento de fuso horário para hoje.

var today = new Date();
var todaysTimeZone = today.getTimezoneOffset();

console.log('todaysTimeZone : ' + todaysTimeZone)

A resposta é: ? - Depende da época do ano

Se o deslocamento de fuso horário de hoje e o deslocamento do fuso horário de verão forem iguais, E as compensações de fuso horário no verão e no inverno forem diferentes, então, por dedução lógica, hoje não deve estar no DST.

Você pode omitir a comparação entre as compensações de fuso horário de verão e inverno, (saber se o horário de verão é usado para esse fuso horário) e apenas comparar a diferença de fuso horário atual com a compensação TZ de verão e sempre obter a resposta correta?

today's TZ Offset !== Summer TZ Offset

Bem, hoje é no inverno ou no verão? Se você soubesse disso, poderia aplicar a seguinte lógica:

if ( it_is_winter && ( todays_TZ_Offset !== summer_TZ_Offset) {
  var are_We_In_DST = true;
}

Mas o problema é que você não sabe se a data de hoje é no inverno ou no verão. Cada fuso horário pode ter suas próprias regras para quando o horário de verão é iniciado e interrompido. Você precisa acompanhar as regras de cada fuso horário para cada fuso horário do mundo. Então, se há uma maneira melhor e mais fácil, então você pode fazê-lo da maneira melhor e mais fácil.

O que nos resta é que você precisa saber se esse fuso horário usa DST e comparar o deslocamento de fuso horário atual com o deslocamento do fuso horário de verão. Isso sempre lhe dará uma resposta confiável.

A lógica final é:

if ( DST_Is_Used_In_This_Time_Zone && ( todays_TZ_Offset !== summer_TZ_Offset) {
  var are_We_In_DST = true;
}

Função para determinar se o fuso horário no navegador usa DST:

function is_DST_Used_In_This_TimeZone() {
  var Jan_Date, jan_Timezone_OffSet, July_Date, july_Timezone_OffSet 
      offsetsNotEqual, thisYear, today;

  today = new Date();//Create a date object that is now
  thisYear = today.getFullYear();//Get the year as a number

  Jan_Date = new Date(thisYear, 0, 1);//Month is zero indexed - Jan is zero
  jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();

  console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)

  July_Date = new Date(thisYear, 6, 1);
  july_Timezone_OffSet = July_Date.getTimezoneOffset();

  console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

  offsetsNotEqual = july_Timezone_OffSet !== jan_Timezone_OffSet;//True if not equal

  console.log('offsetsNotEqual: ' + offsetsNotEqual);

  return offsetsNotEqual;//If the offsets are not equal for summer and
       //winter then the only possible reason is that DST is used for
       //this time zone
}

Você está perto, mas um pouco fora. Você nunca precisa calcular seu próprio tempo, pois é resultado do seu próprio relógio. Ele pode detectar se você está usando o horário de verão em seu local, mas não para um local remoto produzido pelo deslocamento:

newDateWithOffset = new Date(utc + (3600000*(offset)));

Isso ainda estará errado e fora de uma hora se estiverem no horário de verão. Você precisa de uma conta de tempo remoto se eles estiverem dentro do horário de verão ou não e ajustar de acordo. tente calcular isso e mudar o relógio para - digamos, 2/1/2015 e reiniciar o relógio uma hora como se estivesse fora do horário de verão. Em seguida, calcule para um deslocamento para um lugar que ainda deve estar duas horas atrasado. Ele irá mostrar uma hora à frente da janela de duas horas. Você ainda precisa contabilizar a hora e ajustar. Eu fiz isso para NY e Denver e sempre vou a incorreta (hora à frente) em Denver.





dst