Como verificar se o DST (Horário de verão) está em vigor e, se estiver, o deslocamento?

154

Este é um pouco do meu código JS para o qual é 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);

Quero obter a data e hora em "atrás", mas se o horário de verão 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 vigor ou não.

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

Jo Smo
fonte

Respostas:

313

Esse código usa o fato de getTimezoneOffsetretornar um valor maior durante o horário padrão versus o horário de verão (DST). Assim, determina a saída esperada durante o horário padrão e compara se a saída da data especificada é igual (padrão) ou menor (DST).

Observe que getTimezoneOffsetretorna números positivos de minutos para zonas a oeste do UTC, que geralmente são indicadas como horas negativas (já que estão "atrasadas" no UTC). Por exemplo, Los Angeles é UTC – 8h padrão, UTC-7h DST. getTimezoneOffsetretornos 480(480 minutos positivos) em dezembro (inverno, horário padrão), em vez de -480. Retorna números negativos para o Hemisfério Oriental (como -600Sydney no inverno, apesar de estar "à frente" ( UTC + 10h ).

Date.prototype.stdTimezoneOffset = function () {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);
    return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}

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

var today = new Date();
if (today.isDstObserved()) { 
    alert ("Daylight saving time!");
}
Sheldon Griffin
fonte
28
Eu posso verificar se isso funciona internacionalmente. Atualmente, não há fusos horários que usem qualquer forma de horário de verão em que 1º de janeiro e 1º de julho estejam dentro ou fora do período de verão. Além disso, em todos os fusos horários no TZDB ( com uma exceção trivial ), o maior dos dois deslocamentos é o deslocamento do horário de verão. Como o JavaScript getTimezoneOffsetretorna o valor inverso, Math.maxestá retornando o deslocamento padrão . O código está correto.
Matt Johnson-Pint
7
No entanto, se algum fuso horário alterar sua definição de modo que 1º de janeiro e 1º de julho estejam no horário de verão ou não no horário de verão (e o horário de verão ainda se aplica), esse código não funcionará nessa zona.
Matt Johnson-Pint
9
Isso não funciona em geral, por exemplo, existem países que não observam o horário de verão em certos anos e também alguns países revertem o horário de verão durante o Ramadã. Além disso, a definição do ECMAScript para Data está quebrada e também o tratamento da variável de ambiente TZ está quebrado em algumas implementações. Tudo isso combinado torna esse método não confiável. É melhor usar uma biblioteca que não use Date, por exemplo, timezonecomplete
rogierschouten
5
Esse código não funciona em países que não observam o horário de verão, como por exemplo a África do Sul ou a Islândia; ou seja, se você o usar para comparar com outros fusos horários nesses países, ele não mostrará os horários corretos por lá. Sugira o uso de UTC até o fim e verifique manualmente se a hora está dentro de um determinado intervalo de horário de verão. Depois, basta alterar o deslocamento normal do UTC em +1 para obter o horário de verão.
Kebman
1
Como isso pode estar correto? A Alemanha, por exemplo, entrou no horário de verão em 30/10/2016, enquanto os EUA entraram uma semana depois, em 06/11/2016. Informações ruins como essa são o que causa coisas assim: macworld.co.uk/news/apple/…
Daniel F
22

Crie duas datas: uma em junho e outra em janeiro. Compare seus valores getTimezoneOffset ().

  • se deslocamento de janeiro> deslocamento de junho, o cliente estiver no hemisfério norte
  • se deslocamento de janeiro <deslocamento de junho, o cliente está no hemisfério sul
  • se não houver diferença, o fuso horário do cliente não observa o horário de verão

Agora verifique getTimezoneOffset () da data atual.

  • se for igual a junho, hemisfério norte, o fuso horário atual é DST (+1 hora)
  • se for igual a janeiro, hemisfério sul, o fuso horário atual é DST (+1 hora)
Jon Nylander
fonte
Por que você precisa dos hemisférios? não seria suficiente dizer que se getTimezoneOffset () para a data atual for igual ao menor dos dois getTimezoneOffset (), então seu horário de verão? [e a diferença é a diferença entre os dois?]
epeleg 6/11/14
Você não precisa dos hemisférios, como a resposta aceita demonstra claramente :) #
919 Jon Nylander
Isso não vai funcionar. A melhor coisa a fazer é garantir que você use os horários UTC e defina manualmente o deslocamento para a região que deseja. Em seguida, encontre manualmente o início e o término do horário de verão para a mesma região (se houver). Você deseja verificar se o horário para essa região está dentro do intervalo DST ou não e, em seguida, atualize o deslocamento correspondentemente com +1. Isso torna possível comparar os países que observam o horário de verão e os que não observam.
Kebman
A questão é como determinar se o horário de verão está em vigor no momento no fuso horário da máquina cliente Kebman, não como exibir datas, os clientes da Web já lidam com isso para você.
Jon Nylander
Você deve verificar entre janeiro e julho (ou fevereiro e agosto, março e setembro etc.) porque eles têm um intervalo de 6 meses.
precisa saber é o seguinte
17

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


A idéia é que, como nenhum país observa o horário de verão com duração de 7 meses [1] , em uma área que observa o horário de verão, o deslocamento da hora 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 pega um objeto de data d, e retorna truese o horário de verão estiver em vigor para essa data e falsese não estiver:

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(); 
}
Toastrackenigma
fonte
1
Isso funciona, mas se não houver horário de verão no fuso horário atual, o resultado também será verdadeiro, o que não está correto. Se você alternar para Math.max(...) != d.get...(), ele retornará verdadeiro se o horário de verão for observado no fuso horário especificado E a data estiver atualmente no horário de verão. Se o horário de verão não for observado ou a data corresponder ao deslocamento padrão, ele retornará falso.
GreySage 29/03/19
12

Hoje me deparei com esse mesmo problema, mas como o horário de verão começa e para em horários diferentes dos EUA (pelo menos no meu entendimento), 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);

Em seguida, basta comparar o deslocamento do fuso horário atual com o horário de verão e o DSDS para ver qual deles corresponde.

Aaron Cole
fonte
É assim que fazemos também. Ou seja, calcule as horas do ano em que o horário de verão é alterado no fuso horário de destino e calcule as compensações para o dia atual e a data da alteração mais recente. Eles diferem por uma hora ou são iguais (supondo que o fuso horário em questão seja um deslocamento de hora).
Heather
Não há necessidade de criar valores 365, uma abordagem de pesquisa binária que para assim que uma alteração no deslocamento é determinada deve ser muito mais eficiente, mesmo onde o horário de verão não é observado. Todas essas abordagens pressupõem que os locais observam o horário de verão todos os anos, o que não é necessariamente verdade. Os locais adotam e abandonam o horário de verão de tempos em tempos (embora o ECMAScript assuma as regras atuais, independentemente de sua área, sempre aplicadas).
RobG 16/10
2
Rob - como você pode fazer isso através de uma busca binária, se você não sabe onde procurar (ou seja, é o lugar que você está procurando está acima ou abaixo de você r ponto de teste?)
epeleg
9

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 consideração todos os comentários e respostas sugeridas anteriormente, e especificamente:

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

2) Ele não assume que o horário de verão (se houver) seja necessariamente em julho e funcionará mesmo que em algum momento e local seja em qualquer mês. No entanto, em termos de desempenho, ele funcionará mais rápido se de fato julho (ou quase meses) for de fato o horário de verão.

3) Na pior das hipóteses, ele comparará o getTimezoneOffset do primeiro de cada mês. [e faça isso uma vez por ano testado].

A suposição que ele ainda faz é que, se houver um período de horário de verão, será maior que um mês.

Se alguém quiser remover essa suposição, ele pode mudar o loop para algo mais parecido com o que é fornecido pela Aaron Cole - mas eu ainda pularia meio ano à frente e sairia do loop quando forem encontradas duas compensações diferentes]

epeleg
fonte
4

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

moment # 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
Daniel F
fonte
Eu tentei var moment = require ('moment'); this.logger.info (moment ([2011, 2, 12]). isDST ()); this.logger.info (moment ([2011, 2, 14]). isDST ()); ambas são falsas
Logan_B
As datas de alteração do horário de verão variam entre países , mesmo entre estados do mesmo país (ou seja, o estado do Arizona). Nos EUA, foi em 13/03/2011, enquanto na Alemanha, em 31/03/2011. Assim, o resultado será diferente dependendo de qual moment.js do fuso horário é configurado para trabalhar.
Daniel F
1
Ela varia mesmo dentro do estado do Arizona timeanddate.com/time/us/arizona-no-dst.html
Daniel F
3

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

Documentos da Web 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 Internet Assigned Numbers Authority (iana)

fusos horários de iana

Uma tabela de fusos horários bem formatada é fornecida por joda.org

fusos horários

+00: 00 ou Etc / GMT é hora de Greenwich

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

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

Portanto, o horário America / New_York no horário de verão (inverno) é uma hora antes do horário normal. Assim, por exemplo, o que normalmente eram 17:00 da tarde na cidade de Nova York no verão, agora são 16:00 da América / Nova_York no horário de verão. O nome "America / New_York" é um nome de fuso horário "Long Format". A costa leste dos EUA normalmente chama seu fuso horário Horário Padrão do Leste (EST)

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

Veja a tabela de fuso horário em joda.org e encontre o fuso horário para "America / New_York". Ele terá um sinal negativo na frente do deslocamento padrão.

A Terra gira no sentido anti-horário no seu eixo. Uma pessoa vê o nascer do sol em Greenwich vê o nascer do sol 5 horas antes de alguém em Nova York ver 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 verá 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á recebendo o status do horário de verão ou não, sem precisar testar todos os fusos horários em diferentes épocas do ano.

Imagine que seja novembro na cidade de Nova York, e os relógios tenham atrasado uma hora. No verão, na cidade de Nova York, o deslocamento é de 240 minutos ou 4 horas.

Você pode testar isso criando uma data em julho e 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 das ferramentas do desenvolvedor do navegador?

Resposta é: 240

Portanto, agora você pode criar uma data em janeiro e ver o que o 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)

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 maior que o deslocamento de verão? Ou o verão compensou menos que o inverno? Se houver uma diferença entre as compensações de fuso horário de verão e inverno, você poderá assumir que o horário de verão está sendo usado para esse fuso horário. Mas isso não informa se hoje está usando o horário de verão para o fuso horário do navegador. Portanto, você precisará obter o deslocamento do 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 de fuso horário de verão forem os mesmos, E as compensações de fuso horário de verão e inverno forem diferentes, por dedução lógica, hoje NÃO deverá estar no horário de verão.

Você pode omitir a comparação das compensações de fuso horário de verão e inverno (para saber se o horário de verão é usado para esse fuso horário) e apenas comparar o deslocamento de fuso horário de hoje com o deslocamento de TZ do verão e obter sempre 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. Todo fuso horário pode ter suas próprias regras para quando o horário de verão inicia e para. Você precisaria acompanhar as regras de todos os fusos horários para todos os fusos horários do mundo. Portanto, se houver uma maneira melhor e mais fácil, é melhor fazê-lo da maneira melhor e mais fácil.

O que nos resta é que você precisa saber se esse fuso horário usa o horário de verão e comparar o deslocamento de fuso horário de hoje com o deslocamento de 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
}
Alan Wells
fonte
1
De acordo com o dateandtime.com, o horário de verão começou em 10 de março de 2019 e, portanto, é no verão, não no inverno, e o deslocamento do horário de verão de Nova York é -4, e não -5.
Jk7 #
Se for necessário fazer uma melhoria ou correção na resposta, faça uma edição e ela será revisada.
Alan Wells
2

Use Moment.js ( https://momentjs.com/ )

moment().isDST(); fornecerá se o horário de verão for observado.

Também tem função auxiliar para calcular o tempo relativo para você. Você não precisa fazer cálculos manuais, por exemplomoment("20200105", "YYYYMMDD").fromNow();

Santhosh S
fonte
1

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

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

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

Larry Enzer
fonte
1

Descobri que o uso da biblioteca Moment.js com alguns dos conceitos descritos aqui (comparando janeiro a junho) funciona muito bem.

Esta função simples retornará se o fuso horário em que 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 o fuso horário para uma zona não DST, por exemplo, o Arizona retornará falso, enquanto EST ou PST retornará verdadeiro.

insira a descrição da imagem aqui

Nico Westerdale
fonte
1

Solução à prova de futuro que funciona em todos os fusos horários

  1. Seja xo número esperado de milissegundos no ano de interesse sem considerar o horário de verão.
  2. Seja yo número de milissegundos desde a época desde o início do ano da data de interesse.
  3. Seja zo número de milissegundos desde a época da data e hora completas do interesse
  4. Vamos tser a subtração de ambos xe yde z: z - y - x. Isso produz o deslocamento devido ao horário de verão.
  5. Se tfor zero, o horário de verão não está em vigor. Se tnão for zero, o horário de verão está em vigor.

(function(){"use strict";
function dstOffsetAtDate(dateInput) {
    var fullYear = dateInput.getFullYear()|0;
	// "Leap Years are any year that can be exactly divided by 4 (2012, 2016, etc)
 	//   except if it can be exactly divided by 100, then it isn't (2100,2200,etc)
 	//	  except if it can be exactly divided by 400, then it is (2000, 2400)"
	// (https://www.mathsisfun.com/leap-years.html).
    var isLeapYear = ((fullYear & 3) | (fullYear/100 & 3)) === 0 ? 1 : 0;
	// (fullYear & 3) = (fullYear % 4), but faster
    //Alternative:var isLeapYear=(new Date(currentYear,1,29,12)).getDate()===29?1:0
    var fullMonth = dateInput.getMonth()|0;
    return (
        // 1. We know what the time since the Epoch really is
        (+dateInput) // same as the dateInput.getTime() method
        // 2. We know what the time since the Epoch at the start of the year is
        - (+new Date(fullYear, 0, 0)) // day defaults to 1 if not explicitly zeroed
        // 3. Now, subtract what we would expect the time to be if daylight savings
        //      did not exist. This yields the time-offset due to daylight savings.
        - ((
            ((
                // Calculate the day of the year in the Gregorian calendar
                // The code below works based upon the facts of signed right shifts
                //    • (x) >> n: shifts n and fills in the n highest bits with 0s 
                //    • (-x) >> n: shifts n and fills in the n highest bits with 1s
                // (This assumes that x is a positive integer)
                (31 & ((-fullMonth) >> 4)) + // January // (-11)>>4 = -1
                ((28 + isLeapYear) & ((1-fullMonth) >> 4)) + // February
                (31 & ((2-fullMonth) >> 4)) + // March
                (30 & ((3-fullMonth) >> 4)) + // April
                (31 & ((4-fullMonth) >> 4)) + // May
                (30 & ((5-fullMonth) >> 4)) + // June
                (31 & ((6-fullMonth) >> 4)) + // July
                (31 & ((7-fullMonth) >> 4)) + // August
                (30 & ((8-fullMonth) >> 4)) + // September
                (31 & ((9-fullMonth) >> 4)) + // October
                (30 & ((10-fullMonth) >> 4)) + // November
                // There are no months past December: the year rolls into the next.
                // Thus, fullMonth is 0-based, so it will never be 12 in Javascript
                
                (dateInput.getDate()|0) // get day of the month
				
            )&0xffff) * 24 * 60 // 24 hours in a day, 60 minutes in an hour
            + (dateInput.getHours()&0xff) * 60 // 60 minutes in an hour
            + (dateInput.getMinutes()&0xff)
        )|0) * 60 * 1000 // 60 seconds in a minute * 1000 milliseconds in a second
        - (dateInput.getSeconds()&0xff) * 1000 // 1000 milliseconds in a second
        - dateInput.getMilliseconds()
    );
}

// Demonstration:
var date = new Date(2100, 0, 1)
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
    console.log(date.getMonth()+":\t"+dstOffsetAtDate(date)/60/60/1000+"h\t"+date);
date = new Date(1900, 0, 1);
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
    console.log(date.getMonth()+":\t"+dstOffsetAtDate(date)/60/60/1000+"h\t"+date);

// Performance Benchmark:
console.time("Speed of processing 16384 dates");
for (var i=0,month=date.getMonth()|0; i<16384; i=i+1|0)
    date.setMonth(month=month+1+(dstOffsetAtDate(date)|0)|0);
console.timeEnd("Speed of processing 16384 dates");
})();

Acredito que o snippet de código acima é superior a todas as outras respostas postadas aqui por vários motivos.

  • Essa resposta funciona em todos os fusos horários, até na Antártica / Casey .
  • O horário de verão está sujeito a alterações. Pode ser que daqui a 20 anos, algum país possa ter 3 períodos de horário de verão em vez do 2. normal. Esse código lida com esse caso retornando o deslocamento do horário de verão em milissegundos, não apenas se o horário de verão está em vigor ou não.
  • O tamanho dos meses do ano e a maneira como os Anos bissextos funcionam se encaixam perfeitamente para manter nosso tempo na pista com o sol. Heck, funciona tão perfeitamente que tudo o que fazemos é ajustar meros segundos aqui e ali . Nosso sistema atual de anos bissextos está em vigor desde 24 de fevereiro de 1582 e provavelmente permanecerá em vigor no futuro próximo.
  • Esse código funciona em fusos horários que não usam o horário de verão.
  • Esse código funciona em tempos históricos anteriores à implementação do horário de verão (como nos anos 1900).
  • Esse código é otimizado em número máximo máximo e não deve causar problemas se for chamado em um loop restrito. Depois de executar o snippet de código acima, role para baixo até a parte inferior da saída para ver a referência de desempenho. Meu computador é capaz de processar 16384 datas em ~ 97ms no Chrome.

No entanto, se você não estiver se preparando para mais de 2 períodos de horário de verão, o código abaixo pode ser usado para determinar se o horário de verão está em vigor como um booleano.

function isDaylightSavingsInEffect(dateInput) {
    // To satisfy the original question
    return dstOffsetAtDate(dateInput) !== 0;
}
Jack Giffin
fonte
0

Recentemente, precisei criar uma string de data com UTC e DST e, com base na resposta de Sheldon, montei isso:

Date.prototype.getTimezone = function(showDST) {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);

    var utcOffset = new Date().getTimezoneOffset() / 60 * -1;
    var dstOffset = (jan.getTimezoneOffset() - jul.getTimezoneOffset()) / 60;

    var utc = "UTC" + utcOffset.getSign() + (utcOffset * 100).preFixed(1000);
    var dst = "DST" + dstOffset.getSign() + (dstOffset * 100).preFixed(1000);

    if (showDST) {
        return utc + " (" + dst + ")";
    }

    return utc;
}
Number.prototype.preFixed = function (preCeiling) {
    var num = parseInt(this, 10);
    if (preCeiling && num < preCeiling) {
        num = Math.abs(num);
        var numLength		 = num.toString().length;
        var preCeilingLength = preCeiling.toString().length;
        var preOffset		 = preCeilingLength - numLength;
        for (var i = 0; i < preOffset; i++) {
            num = "0" + num;
        }
    }
    return num;
}
Number.prototype.getSign = function () {
    var num	 = parseInt(this, 10);
    var sign = "+";
    if (num < 0) {
        sign = "-";
    }
    return sign;
}

document.body.innerHTML += new Date().getTimezone() + "<br>";
document.body.innerHTML += new Date().getTimezone(true);
<p>Output for Turkey (UTC+0200) and currently in DST: &nbsp; UTC+0300 (DST+0100)</p>
<hr>

akinuri
fonte
0

Existe um problema ao usar o Date.toString().indexOf('Daylight Time') > -1

"" + new Date()

Sáb 01 de janeiro 100050 00:00:00 GMT-0500 ( horário padrão oriental )

"" + new Date(...)

Dom 01 de maio 100033 00:00:00 GMT-0400 ( horário de verão oriental )

Isso parece compatível com todos os navegadores.

YC
fonte
Sim, não funciona em todo o mundo. No verão na Europa, você recebe"Thu Jul 02 2020 14:07:01 GMT+0200 (Central European Summer Time)"
Tadej Krevh
0

Estilo ES6

Math.min(...[0, 6].map(v => new Date(95, v, 1).getTimezoneOffset() * -1));
nkitku
fonte