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?

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!");
}

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)

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(); 
}

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.


É 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]


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

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
}

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();


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.


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


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;
}

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>


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.


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));
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.