Come verificare se è in vigore l'ora legale (ora legale) e, in tal caso, l'offset?


154

Questo è un po 'del mio codice JS per il quale è necessario:

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

Voglio ottenere il datetime in "ago", ma se è in uso l'ora legale, le date sono scadute di 1 ora. Non so come verificare se l'ora legale è in vigore o meno.

Come posso sapere quando inizia e finisce l'ora legale?

Risposte:


313

Questo codice utilizza il fatto che getTimezoneOffsetrestituisce un valore maggiore durante l'ora solare rispetto all'ora legale (DST). Pertanto, determina l'output previsto durante l'ora solare e confronta se l'output di una determinata data è uguale (standard) o inferiore (ora legale).

Si noti che getTimezoneOffsetrestituisce un numero positivo di minuti per le zone a ovest di UTC, che di solito sono indicate come ore negative (poiché sono "dietro" UTC). Ad esempio, Los Angeles è UTC-8h Standard, UTC-7h DST. getTimezoneOffsetritorni 480(480 minuti positivi) a dicembre (inverno, ora solare), anziché -480. Restituisce numeri negativi per l'Emisfero Orientale (come -600per Sydney in inverno, nonostante questo sia "avanti" ( 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
Posso verificare che funzioni a livello internazionale. Attualmente non ci sono fusi orari che utilizzano qualsiasi forma di ora legale in cui sia il 1 ° gennaio che il 1 ° luglio sono entrambi in o entrambi fuori dal periodo di ora legale. Inoltre, in tutti i fusi orari nel TZDB ( con una banale eccezione ) il maggiore dei due offset è l'offset DST. Poiché JavaScript getTimezoneOffsetrestituisce il valore inverso, Math.maxrestituisce effettivamente l' offset standard . Il codice è corretto
Matt Johnson-Pint,

7
Tuttavia, se un fuso orario dovesse mai cambiare la sua definizione in modo tale che sia il 1 ° gennaio sia il 1 ° luglio siano entrambi in ora legale o entrambi non in ora legale (e l'ora legale si applica ancora), allora questo codice non funzionerebbe in quella zona.
Matt Johnson-Pint,

9
Questo non funziona in generale, ad esempio ci sono paesi che non osservano l'ora legale in alcuni anni e anche alcuni paesi ripristinano l'ora legale durante il Ramadan. Oltre a ciò, la definizione ECMAScript per Date è interrotta e anche la gestione della variabile d'ambiente TZ è interrotta in alcune implementazioni. Tutto ciò combinato rende questo metodo inaffidabile. Stai meglio usando una libreria che non usa Date es. Timezonecomete
rogierschouten,

5
Questo codice non funziona in paesi che non osservano l'ora legale, come ad esempio il Sudafrica o l'Islanda; il che significa che se lo usi per confrontare con altri fusi orari in quei paesi, non mostrerà l'ora corretta laggiù. Suggerisci di utilizzare UTC fino in fondo e controlla manualmente se l'ora è ora entro un certo intervallo di ora legale. Quindi è solo una questione di cambiare l'offset UTC dell'ora normale di +1 per ottenere l'ora legale.
Kebman,

1
Come può essere corretto? La Germania, ad esempio, è entrata nell'ora legale il 30-10-2016, mentre gli Stati Uniti sono entrati una settimana dopo il 6-11-2016. Una cattiva informazione come questa è ciò che fa accadere cose del genere: macworld.co.uk/news/apple/…
Daniel F,

22

Crea due date: una a giugno, una a gennaio. Confronta i loro valori getTimezoneOffset ().

  • se offset di gennaio> offset di giugno, il client si trova nell'emisfero settentrionale
  • se offset di gennaio <offset di giugno, il client è nell'emisfero sud
  • se nessuna differenza, il fuso orario del client non osserva l'ora legale

Ora controlla getTimezoneOffset () della data corrente.

  • se uguale a giugno, emisfero nord, il fuso orario corrente è ora legale (+1 ora)
  • se uguale a gennaio, emisfero sud, il fuso orario corrente è ora legale (+1 ora)

Perché hai bisogno degli emisferi? non basterebbe dire che se getTimezoneOffset () per la data corrente è uguale al più piccolo dei due getTimezoneOffset () allora il suo DST? [e l'offset è la differenza tra i due?]
epeleg

Non hai bisogno degli emisferi come dimostra chiaramente la risposta accettata :)
Jon Nylander,

Questo non funzionerà. La cosa migliore da fare è assicurarsi di utilizzare i tempi UTC e impostare manualmente l'offset per la regione desiderata. Quindi trova manualmente l'inizio e la fine dell'ora legale per la stessa regione (se presente). Quindi si desidera verificare se il tempo per quella regione è compreso o meno nell'intervallo DST, quindi aggiornare l'offset in modo corrispondente con +1. Ciò consente di confrontare i paesi che osservano l'ora legale e quelli che non lo fanno.
Kebman,

La domanda è come determinare se l'ora legale è in vigore al momento nel fuso orario della macchina client Kebman, non come visualizzare le date, i client Web già gestiscono questo per te.
Jon Nylander,

Dovresti controllare tra gennaio e luglio (o febbraio e agosto, marzo e settembre, ecc.) Perché sono distanti 6 mesi.
kpull1

17

Questa risposta è abbastanza simile alla risposta accettata, ma non sostituisce il Dateprototipo e utilizza solo una chiamata di funzione per verificare se è in vigore l'ora legale, anziché due.


L'idea è che, dal momento che nessun paese osserva l'ora legale che dura 7 mesi [1] , in un'area che osserva l'ora legale la differenza rispetto all'ora UTC di gennaio sarà diversa da quella di luglio.

Mentre l'ora legale sposta gli orologi in avanti , JavaScript restituisce sempre un valore maggiore durante l'ora solare. Pertanto, ottenere l'offset minimo tra gennaio e luglio otterrà l'offset del fuso orario durante l'ora legale.

Quindi controlliamo se il fuso orario delle date è uguale a quel valore minimo. Se lo è, allora siamo in ora legale; altrimenti non lo siamo.

La seguente funzione utilizza questo algoritmo. Prende un oggetto data de restituisce truese l'ora legale è in vigore per quella data e falsese non lo è:

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
Funziona, ma se non è presente l'ora legale nell'attuale fuso orario, anche questo risulterà vero, il che non è corretto. Se lo si commuta su Math.max(...) != d.get...(), tornerà vero se si osserva l'ora legale nel fuso orario specificato E la data è attualmente in ora legale. Se l'ora legale non viene osservata o la data corrisponde all'offset standard, restituirà false.
GreySage,

12

Oggi ho dovuto affrontare lo stesso problema, ma dato che la nostra ora legale inizia e si interrompe in orari diversi dagli Stati Uniti (almeno dalla mia comprensione), ho utilizzato un percorso leggermente diverso ..

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

Quindi confronta semplicemente l'offset del fuso orario corrente con l'ora legale e non l'ora legale per vedere quale corrisponde.


Questo è anche il modo in cui lo facciamo. Cioè, capire i periodi dell'anno in cui l'ora legale cambia nel fuso orario target e calcolare gli offset per il giorno corrente e la data di modifica più recente. Differiranno di un'ora o saranno uguali (supponendo che il fuso orario in questione sia un offset di ora).
Heather,

Non è necessario creare 365 valori, un approccio di ricerca binaria che si interrompe non appena viene determinato un cambiamento nell'offset dovrebbe essere molto più efficiente, anche quando non si osserva l'ora legale. Tutti questi approcci presuppongono che i luoghi osservino l'ora legale ogni anno, il che non è necessariamente vero. I luoghi adottano e abbandonano di tanto in tanto l'ora legale (anche se ECMAScript assume le regole attuali, qualunque esse siano, applicate sempre).
RobG

2
Rob - come puoi farlo tramite una ricerca binaria se non sai dove cercare (cioè il posto che stai cercando è sopra o sotto il tuo punto di prova?)
epeleg

9

Sulla base del commento di Matt Johanson sulla soluzione fornita da Sheldon Griffin, ho creato il seguente codice:

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

Cerca di ottenere il meglio da tutti i mondi prendendo in considerazione tutti i commenti e le risposte precedentemente suggerite e specificamente:

1) Memorizza nella cache il risultato per stdTimezoneOffset all'anno in modo da non doverlo ricalcolare durante il test di più date nello stesso anno.

2) Non presuppone che l'ora legale (se esiste affatto) sia necessariamente a luglio, e funzionerà anche se ad un certo punto e in qualche luogo sarà ogni mese. Tuttavia, dal punto di vista delle prestazioni, funzionerà più velocemente se effettivamente luglio (o quasi i mesi) sono davvero l'ora legale.

3) Caso peggiore, confronterà getTimezoneOffset del primo di ogni mese. [e farlo una volta per anno testato].

Il presupposto che fa ancora è che se c'è un periodo di ora legale è più grande di un solo mese.

Se qualcuno vuole rimuovere quell'ipotesi, può cambiare loop in qualcosa di più simile a quello che è nel solutin fornito da Aaron Cole - ma salterei ancora mezzo anno avanti e uscirei dal loop quando vengono trovati due offset diversi]


4

La libreria moment.js fornisce un .isDst()metodo sui suoi oggetti time.

moment # isDST controlla se il momento corrente è nell'ora legale.

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

Ho provato var moment = require ('moment'); this.logger.info (moment ([2011, 2, 12]). isDST ()); this.logger.info (moment ([2011, 2, 14]). isDST ()); entrambi sono falsi
Logan_B,

Le date di modifica dell'ora legale variano tra i paesi , anche tra gli stati dello stesso paese (ovvero lo stato dell'Arizona). Negli Stati Uniti era il 13-03-2011, mentre in Germania era il 31-03-2011. Quindi il risultato differirà a seconda del fuso orario moment.js in cui è configurato per funzionare.
Daniel F

1
Varia anche all'interno dello stato dell'Arizona timeanddate.com/time/us/arizona-no-dst.html
Daniel F

3

Il getTimezoneOffset()metodo in JavaScript, in un browser, restituisce il numero di offset dei minuti dal fuso orario 00:00. Ad esempio, il fuso orario America / New_York in Ora legale (DST) restituisce il numero 300. 300 minuti sono 5 ore di differenza da zero. 300 minuti divisi per 60 minuti sono 5 ore. Ogni fuso orario viene confrontato con il fuso orario zero, +00: 00 / Etc / GMT / ora di Greenwich.

Documenti Web MDN

La prossima cosa che devi sapere è che l'offset ha il segno opposto del fuso orario effettivo.

Le informazioni sui fusi orari sono gestite dall'Internet Assigned Numbers Authority (iana)

fusi orari iana

Una tabella di fusi orari ben formattata è fornita da joda.org

fusi orari joda-time

+00: 00 o Etc / GMT è l'ora di Greenwich

Tutti i fusi orari sono sfalsati da +00: 00 / "Etc / GMT" / ora di Greenwich

L'ora legale è sempre precedente all'ora "normale" in estate. Riporti gli orologi nella stagione autunnale. (Slogan "Fall Back" per ricordare cosa fare)

Pertanto, l'ora di America / New_York nell'ora legale (inverno) è un'ora prima dell'orario normale. Quindi, ad esempio, quello che era normalmente alle 17:00 nel pomeriggio a New York City in estate, ora è alle 16:00 America / New_York l'ora legale. Il nome "America / New_York" ora è un nome di fuso orario "Long Format". La costa orientale degli Stati Uniti in genere chiama il loro fuso orario Eastern Standard Time (EST)

Se si desidera confrontare l'offset del fuso orario di oggi con l'offset del fuso orario di un'altra data, è necessario sapere che il segno matematico (+/- "Positivo / Negativo") dell'offset del fuso orario è l'opposto del fuso orario.

Guarda la tabella dei fusi orari su joda.org e trova il fuso orario per "America / New_York" Avrà un segno negativo davanti all'offset standard.

La terra ruota in senso antiorario sul suo asse. Una persona che guarda l'alba a Greenwich vede l'alba 5 ore prima che qualcuno a New York City vedrà l'alba. E qualcuno sulla costa occidentale degli Stati Uniti vedrà l'alba dopo che qualcuno sulla costa orientale degli Stati Uniti vede l'alba.

C'è un motivo per cui devi sapere tutto questo. In questo modo sarai in grado di determinare logicamente se un codice JavaScript sta ottenendo correttamente o meno lo stato dell'ora legale, senza bisogno di testare ogni fuso orario in diversi periodi dell'anno.

Immagina che sia novembre a New York City e che gli orologi siano arretrati di un'ora. In estate a New York City, l'offset è di 240 minuti o 4 ore.

È possibile verificare ciò creando una data che è in luglio e quindi ottenere l'offset.

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

console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

Cosa verrà stampato nel registro della console degli strumenti di sviluppo del browser?

La risposta è: 240

Quindi, ora puoi creare una data a gennaio e vedere cosa restituisce il tuo browser per un offset di fuso orario per la stagione invernale.

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)

La risposta è: 300

Ovviamente 300 è più grande di 240. Quindi, cosa significa? Dovresti scrivere un codice che verifichi che l'offset invernale è maggiore dell'offset estivo? O la compensazione estiva è inferiore alla compensazione invernale? Se esiste una differenza tra gli offset del fuso orario estivo e invernale, è possibile supporre che l'ora legale venga utilizzata per questo fuso orario. Ma ciò non ti dice se oggi si sta utilizzando l'ora legale per il fuso orario del browser. Quindi, dovrai ottenere l'offset del fuso orario per oggi.

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

console.log('todaysTimeZone : ' + todaysTimeZone)

La risposta è:? - Dipende dal periodo dell'anno

Se l'offset del fuso orario di oggi e l'offset del fuso orario estivo sono uguali, E gli offset del fuso orario estivo e invernale sono diversi, quindi per deduzione logica, oggi NON deve essere in ora legale.

Puoi omettere di confrontare gli offset del fuso orario estivo e invernale (per sapere se l'ora legale è usata per questo fuso orario) e confrontare semplicemente l'offset del fuso orario di oggi con l'offset TZ estivo e ottenere sempre la risposta corretta?

today's TZ Offset !== Summer TZ Offset

Bene, è oggi in inverno o in estate? Se lo sapessi, potresti applicare la seguente logica:

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

Ma il problema è che non sai se la data di oggi è in inverno o in estate. Ogni fuso orario può avere le proprie regole per l'avvio e l'arresto dell'ora legale. Dovresti tenere traccia delle regole di ogni fuso orario per ogni fuso orario nel mondo. Quindi, se c'è un modo migliore e più semplice, allora potresti farlo nel modo migliore e più semplice.

Ciò che ci rimane è che devi sapere se questo fuso orario utilizza l'ora legale e quindi confrontare l'offset del fuso orario di oggi con l'offset del fuso orario estivo. Questo ti darà sempre una risposta affidabile.

La logica finale è:

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

Funzione per determinare se il fuso orario nel browser utilizza l'ora legale:

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
Secondo dateandtime.com l' ora legale è iniziata il 10 marzo nel 2019, e quindi è in estate, non in inverno, e la compensazione dell'ora legale di New York è -4, non -5.
jk7,

Se è necessario apportare un miglioramento o una correzione alla risposta, apportare una modifica e verrà esaminata.
Alan Wells,

2

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

moment().isDST(); ti darà se si osserva il risparmio di luce diurna.

Inoltre ha la funzione di aiuto per calcolare il tempo relativo per te. Non è necessario eseguire calcoli manuali, ad esmoment("20200105", "YYYYMMDD").fromNow();


1

Sei vicino ma un po 'fuori. Non hai mai bisogno di calcolare il tuo tempo in quanto è il risultato del tuo orologio. Può rilevare se si sta utilizzando l'ora legale nella propria posizione ma non per una posizione remota prodotta dall'offset:

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

Questo sarà ancora sbagliato e spento un'ora se sono in ora legale. È necessario disporre di un account orario remoto se si trovano o meno all'interno dell'ora legale e si adeguano di conseguenza. prova a calcolarlo e cambia l'orologio in - diciamo 2/1/2015 e resetta l'orologio indietro di un'ora come se fosse fuori dall'ora legale. Quindi calcolare un offset per un luogo che dovrebbe essere ancora 2 ore indietro. Mostrerà un'ora avanti rispetto alla finestra di due ore. Dovresti comunque tenere conto dell'ora e adeguarti. L'ho fatto per New York e Denver e ho sempre sbagliato (un'ora avanti) a Denver.


1

Ho scoperto che l'uso della libreria Moment.js con alcuni dei concetti descritti qui (confrontando gennaio e giugno) funziona molto bene.

Questa semplice funzione restituirà se il fuso orario in cui si trova l'utente osserva l'ora legale:

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

Un modo semplice per verificare che funzioni (su Windows) consiste nel cambiare il fuso orario in una zona non DST, ad esempio l'Arizona restituirà false, mentre EST o PST restituiranno true.

inserisci qui la descrizione dell'immagine


1

Soluzione a prova di futuro che funziona in tutte le fasce orarie

  1. Lasciate xessere il numero previsto di millisecondi nell'anno di interesse senza tenere conto dell'ora legale.
  2. Lasciate ystare il numero di millisecondi dal momento che l'Epoch dall'inizio del anno dalla data di interesse.
  3. Lasciate zstare il numero di millisecondi da quando l' epoca della data e ora di interesse pieno
  4. Lasciate che tsia la sottrazione di entrambi xe yda z: z - y - x. Ciò produce l'offset dovuto all'ora legale.
  5. Se tè zero, DST non è attivo. Se tnon è zero, l'ora legale è in vigore.

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

Credo che lo snippet di codice sopra riportato sia superiore a tutte le altre risposte pubblicate qui per molte ragioni.

  • Questa risposta funziona in tutti i fusi orari, anche in Antartide / Casey .
  • L'ora legale è molto soggetta a modifiche. Forse tra 20 anni, alcuni paesi potrebbero avere 3 periodi di ora legale invece del normale 2. Questo codice gestisce quel caso restituendo l'offset dell'ora legale in millisecondi, non solo se l'ora legale è in vigore o meno.
  • Le dimensioni dei mesi dell'anno e il modo in cui funzionano Leap Years si adattano perfettamente per mantenere il nostro tempo in pista con il sole. Diamine, funziona così perfettamente che tutto ciò che facciamo è regolare solo pochi secondi qua e là . Il nostro attuale sistema di anni bisestili è in vigore dal 24 febbraio 1582 e probabilmente rimarrà in vigore per il prossimo futuro.
  • Questo codice funziona in fusi orari che non utilizzano l'ora legale.
  • Questo codice funziona in epoche storiche prima dell'implementazione dell'ora legale (come nel 1900).
  • Questo codice è ottimizzato al massimo per numero intero e non dovrebbe dare problemi se chiamato in un ciclo stretto. Dopo aver eseguito lo snippet di codice riportato sopra, scorrere fino alla fine dell'output per visualizzare il benchmark delle prestazioni. Il mio computer è in grado di elaborare 16384 date in ~ 97ms su Chrome.

Tuttavia, se non si sta preparando per più di 2 periodi di ora legale, è possibile utilizzare il codice seguente per determinare se l'ora legale è in effetti un valore booleano.

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

0

Di recente avevo bisogno di creare una stringa di date con UTC e DST, e sulla base della risposta di Sheldon ho messo insieme questo:

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

C'è un problema con l'uso di Date.toString().indexOf('Daylight Time') > -1

"" + new Date()

Lun gen 01 100050 00:00:00 GMT-0500 (Eastern standard Time)

"" + new Date(...)

Dom 01 mag 100033 00:00:00 GMT-0400 ( ora legale orientale )

Questo sembra compatibile con tutti i browser.


Sì, non funziona in tutto il mondo. In estate in Europa, ottieni"Thu Jul 02 2020 14:07:01 GMT+0200 (Central European Summer Time)"
Tadej Krevh il

0

Stile ES6

Math.min(...[0, 6].map(v => new Date(95, v, 1).getTimezoneOffset() * -1));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.