¿Cómo verificar si el horario de verano (DST) está vigente y, de ser así, el desplazamiento?

154

Este es un poco de mi código JS para el que es necesario:

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

Quiero obtener la fecha y hora en "ago", pero si el horario de verano está en uso, las fechas están apagadas en 1 hora. No sé cómo verificar si el horario de verano está vigente o no.

¿Cómo puedo saber cuándo comienza y termina el horario de verano?

Jo Smo
fuente

Respuestas:

313

Este código utiliza el hecho de que getTimezoneOffsetdevuelve un valor mayor durante la hora estándar frente al horario de verano (DST). Por lo tanto, determina la salida esperada durante la hora estándar y compara si la salida de la fecha dada es la misma (estándar) o menor (DST).

Tenga en cuenta que getTimezoneOffsetdevuelve números positivos de minutos para las zonas al oeste de UTC, que generalmente se expresan como horas negativas (ya que están "detrás" de UTC). Por ejemplo, Los Ángeles es UTC – 8h Standard, UTC-7h DST. getTimezoneOffsetvuelve 480(positivo 480 minutos) en diciembre (invierno, hora estándar), en lugar de -480. Devuelve números negativos para el hemisferio oriental (como -600Sydney en invierno, a pesar de que está "por delante" ( 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
fuente
28
Puedo verificar que esto funciona internacionalmente. Actualmente, no hay zonas horarias que utilicen ningún tipo de horario de verano donde el 1 de enero y el 1 de julio estén dentro o fuera del período de horario de verano. Además, en todas las zonas horarias de la TZDB ( con una excepción trivial ) la mayor de las dos compensaciones es el desplazamiento DST. Dado que JavaScript getTimezoneOffsetdevuelve el valor inverso, de Math.maxhecho está devolviendo el desplazamiento estándar . El código es correcto
Matt Johnson-Pint
77
Sin embargo, si alguna zona horaria cambia alguna vez su definición de modo que tanto el 1 de enero como el 1 de julio estén ambos en horario de verano o ambos no en horario de verano (y el horario de verano aún se aplica), entonces este código no funcionaría en esa zona.
Matt Johnson-Pint
9
Esto no funciona en general, por ejemplo, hay países que no han observado el horario de verano en ciertos años y también algunos países revierten el horario de verano durante el Ramadán. Además de eso, la definición de ECMAScript para Fecha está rota y también el manejo de la variable de entorno TZ está roto en algunas implementaciones. Todo esto combinado hace que este método no sea confiable. Es mejor usar una biblioteca que no use Date, por ejemplo, timezonecomplete
rogierschouten
55
Este código no funciona en países que no observan el horario de verano, como por ejemplo Sudáfrica o Islandia; lo que significa que si lo usa para comparar con otras zonas horarias en esos países, no mostrará las horas correctas allí. Sugiera usar UTC todo el tiempo y verifique manualmente si el tiempo ahora está dentro de un cierto rango de DST. Entonces solo es cuestión de cambiar el tiempo normal de compensación UTC por +1 para obtener el horario de verano.
Kebman
1
¿Cómo puede ser esto correcto? Alemania, por ejemplo, ingresó en horario de verano el 30/10/2016, mientras que EE. UU. Ingresó una semana después el 06/11/2016. Mala información como esta es la que hace que sucedan cosas como esta: macworld.co.uk/news/apple/…
Daniel F
22

Cree dos fechas: una en junio y otra en enero. Compare sus valores getTimezoneOffset ().

  • si enero compensa> junio compensa, el cliente está en el hemisferio norte
  • si enero compensa <junio compensa, el cliente está en el hemisferio sur
  • si no hay diferencia, la zona horaria del cliente no observa el horario de verano

Ahora verifique getTimezoneOffset () de la fecha actual.

  • si es igual a junio, hemisferio norte, la zona horaria actual es DST (+1 hora)
  • si es igual a enero, hemisferio sur, la zona horaria actual es DST (+1 hora)
Jon Nylander
fuente
¿Por qué necesitas los hemisferios? ¿no sería suficiente decir que si getTimezoneOffset () para la fecha actual es igual al menor de los dos getTimezoneOffset (), entonces es su horario de verano? [y el desplazamiento es la diferencia entre los dos?]
epeleg
No necesita los hemisferios como lo demuestra claramente la respuesta aceptada :)
Jon Nylander
Esto no funcionara. Lo mejor que puedes hacer es asegurarte de usar las horas UTC y establecer manualmente el desplazamiento para la región que deseas. Luego, busque manualmente el inicio y el final del horario de verano para la misma región (si corresponde). Luego, desea verificar si el tiempo para esa región está dentro del rango DST o no, y luego actualizar el desplazamiento correspondientemente con +1. Esto permite comparar países que observan el horario de verano y aquellos que no lo hacen.
Kebman
La pregunta es cómo determinar si el horario de verano está vigente en el momento en la zona horaria de la máquina cliente Kebman, no cómo mostrar las fechas, los clientes web ya lo manejan por usted.
Jon Nylander
Debe verificar entre enero y julio (o febrero y agosto, marzo y septiembre, etc.) porque tienen 6 meses de diferencia.
kpull1
17

Esta respuesta es bastante similar a la respuesta aceptada, pero no anula el Dateprototipo, y solo usa una llamada de función para verificar si el horario de verano está vigente, en lugar de dos.


La idea es que, dado que ningún país observa el horario de verano que dura 7 meses [1] , en un área que observa el horario de verano, la compensación de la hora UTC en enero será diferente a la de julio.

Mientras que el horario de verano se mueve relojes hacia delante , JavaScript siempre devuelve un mayor valor durante la hora estándar. Por lo tanto, obtener la compensación mínima entre enero y julio obtendrá la compensación de zona horaria durante el horario de verano.

Luego verificamos si la zona horaria de fechas es igual a ese valor mínimo. Si es así, entonces estamos en horario de verano; de lo contrario no lo somos.

La siguiente función usa este algoritmo. Toma un objeto de fecha d, y regresa truesi el horario de verano está vigente para esa fecha, y falsesi no es así:

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
fuente
1
Esto funciona, pero si no hay horario de verano en la zona horaria actual, también resultará verdadero, lo cual no es correcto. Si lo cambia a Math.max(...) != d.get...(), devolverá verdadero si se observa DST en la zona horaria dada Y la fecha está actualmente en DST. Si no se observa el horario de verano o la fecha coincide con el desplazamiento estándar, devolverá falso.
GreySage
12

Me enfrenté a este mismo problema hoy, pero dado que nuestro horario de verano comienza y se detiene en diferentes momentos de los EE. UU. (Al menos, según tengo entendido), utilicé una ruta ligeramente 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);

Luego simplemente compara el desplazamiento de la zona horaria actual con DST y no DST para ver cuál coincide.

Aaron Cole
fuente
Así es como lo hacemos también. Es decir, calcule las épocas del año en que el horario de verano cambia en su zona horaria objetivo y calcule las compensaciones para el día actual y la fecha de cambio más reciente. Diferirán en una hora o serán iguales (suponiendo que la zona horaria en cuestión sea una compensación de hora).
Heather
No es necesario crear 365 valores, un enfoque de búsqueda binaria que se detiene tan pronto como se determina un cambio en la compensación debería ser mucho más eficiente, incluso cuando no se observa el horario de verano. Todos estos enfoques suponen que los lugares observan el horario de verano todos los años, lo cual no es necesariamente cierto. Los lugares adoptan y abandonan el horario de verano de vez en cuando (aunque ECMAScript asume las reglas actuales, cualquiera que sea su área, siempre se aplica).
RobG
2
Rob - ¿cómo se puede hacer esto a través de una búsqueda binaria, si usted no sabe dónde buscar (es decir, es el lugar que busca está por encima o por debajo de r punto de prueba?)
epeleg
9

Basado en el comentario de Matt Johanson sobre la solución provista por Sheldon Griffin, creé el siguiente 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(); 
    };

Intenta obtener lo mejor de todos los mundos teniendo en cuenta todos los comentarios y las respuestas sugeridas anteriormente y específicamente:

1) Almacena en caché el resultado de stdTimezoneOffset por año para que no necesite volver a calcularlo al probar varias fechas en el mismo año.

2) No asume que el horario de verano (si es que existe) es necesariamente en julio, y funcionará incluso en algún momento y en algún lugar en cualquier mes. Sin embargo, en cuanto al rendimiento, funcionará más rápido si efectivamente julio (o cerca de meses) son realmente DST.

3) En el peor de los casos, comparará el getTimezoneOffset del primero de cada mes. [y hacer eso una vez por año probado].

La suposición que aún hace es que si hay un período de horario de verano es mayor que un solo mes.

Si alguien quiere eliminar esa suposición, puede cambiar el ciclo a algo más parecido a lo que ofrece la solución proporcionada por Aaron Cole, pero aún así saltaría medio año adelante y saldría del ciclo cuando se encuentran dos compensaciones diferentes]

epeleg
fuente
4

La biblioteca moment.js proporciona un .isDst()método en sus objetos de tiempo.

moment # isDST comprueba si el momento actual está en el horario de verano.

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
fuente
Intenté var moment = require ('moment'); this.logger.info (momento ([2011, 2, 12]). isDST ()); this.logger.info (momento ([2011, 2, 14]). isDST ()); ambos son falsos
Logan_B
Las fechas de cambio de horario de verano varían entre países , incluso entre los estados del mismo país (es decir, el estado de Arizona). En los Estados Unidos fue el 13-03-2011, mientras que en Alemania fue el 31-03-2011. Por lo tanto, el resultado será diferente dependiendo de la zona horaria en la que moment.js esté configurado para trabajar.
Daniel F
1
Incluso varía dentro del estado de Arizona timeanddate.com/time/us/arizona-no-dst.html
Daniel F
3

El getTimezoneOffset()método en JavaScript, en un navegador, devuelve el número de minutos compensados ​​desde la zona horaria 00:00. Por ejemplo, la zona horaria América / Nueva_York en el horario de verano (DST) devuelve el número 300. 300 minutos es 5 horas de diferencia desde cero. 300 minutos dividido por 60 minutos son 5 horas. Cada zona horaria se compara con la zona horaria cero, +00: 00 / Etc / GMT / hora de Greenwich.

MDN Web Docs

Lo siguiente que debe saber es que el desplazamiento tiene el signo opuesto de la zona horaria real.

La Autoridad de Números Asignados de Internet (iana) mantiene información sobre las zonas horarias.

zonas horarias de iana

Joda.org proporciona una tabla de zonas horarias con un formato agradable

zonas horarias de tiempo joda

+00: 00 o Etc / GMT es hora de Greenwich

Todas las zonas horarias están compensadas desde +00: 00 / "Etc / GMT" / hora de Greenwich

El horario de verano es siempre un horario anterior al horario "regular" del verano. Regresaste tus relojes en la temporada de otoño. (Lema "Fall Back" para recordar qué hacer)

Entonces, el horario de América / Nueva_York en el horario de verano (invierno) es una hora antes del horario normal. Entonces, por ejemplo, lo que normalmente era las 5 pm de la tarde en la ciudad de Nueva York en el verano, ahora son las 4 pm, hora de América / Nueva York en el horario de verano. El nombre de la hora "América / Nueva_York" es un nombre de zona horaria de "Formato largo". La costa este de los EE. UU. Generalmente llama a su zona horaria Hora estándar del este (EST)

Si desea comparar el desplazamiento de la zona horaria actual con el desplazamiento de la zona horaria de otra fecha, debe saber que el signo matemático (+/- "Positivo / Negativo") del desplazamiento de la zona horaria es el opuesto de la zona horaria.

Mire la tabla de zonas horarias en joda.org y encuentre la zona horaria para "América / Nueva_York". Tendrá un signo negativo frente a la compensación estándar.

La tierra gira en sentido antihorario sobre su eje. Una persona que mira el amanecer en Greenwich ve el amanecer 5 horas antes de que alguien en la ciudad de Nueva York vea el amanecer. Y alguien en la costa oeste de los Estados Unidos verá el amanecer después de que alguien en la costa este de los Estados Unidos vea el amanecer.

Hay una razón por la que necesitas saber todo esto. Para que pueda determinar lógicamente si algún código JavaScript obtiene el estado de DST correctamente o no, sin necesidad de probar cada zona horaria en diferentes épocas del año.

Imagine que es noviembre en la ciudad de Nueva York, y los relojes se han retrasado una hora. En el verano en la ciudad de Nueva York, el desplazamiento es de 240 minutos o 4 horas.

Puede probar esto creando una fecha que sea en julio y luego obteniendo el desplazamiento.

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

console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

¿Qué se imprimirá en el registro de la consola de herramientas de desarrollo del navegador?

La respuesta es: 240

Entonces, ahora puede crear una fecha en enero y ver qué devuelve su navegador para un desplazamiento de zona horaria para la temporada de invierno.

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 respuesta es: 300

Obviamente 300 es más grande que 240. Entonces, ¿qué significa esto? ¿Debería escribir un código que pruebe que la compensación de invierno sea mayor que la compensación de verano? ¿O la compensación de verano menos que la compensación de invierno? Si hay una diferencia entre las compensaciones de zona horaria de verano e invierno, entonces puede suponer que se está utilizando DST para esta zona horaria. Pero eso no le dice si hoy está usando DST para la zona horaria de los navegadores. Por lo tanto, deberá obtener el desplazamiento de zona horaria para hoy.

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

console.log('todaysTimeZone : ' + todaysTimeZone)

La respuesta es: ? - Depende de la época del año.

Si el desplazamiento de zona horaria de hoy y el desplazamiento de zona horaria de verano son iguales, Y las compensaciones de zona horaria de verano e invierno son diferentes, entonces, por deducción lógica, hoy NO debe estar en DST.

¿Puede omitir la comparación de las compensaciones de zona horaria de verano e invierno (para saber si se usa DST para esta zona horaria) y simplemente comparar la compensación de zona horaria de hoy con la compensación de TZ de verano y obtener siempre la respuesta correcta?

today's TZ Offset !== Summer TZ Offset

Bueno, ¿hoy es invierno o verano? Si lo supieras, entonces podrías aplicar la siguiente lógica:

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

Pero el problema es que no sabes si la fecha de hoy es invierno o verano. Cada zona horaria puede tener sus propias reglas para cuando el horario de verano comienza y se detiene. Debería realizar un seguimiento de las reglas de cada zona horaria para cada zona horaria del mundo. Entonces, si hay una manera mejor y más fácil, entonces también podrías hacerlo de la mejor manera y más fácil.

Lo que nos queda es que necesita saber si esta zona horaria usa DST y luego comparar el desplazamiento de la zona horaria de hoy con el desplazamiento de la zona horaria de verano. Eso siempre te dará una respuesta confiable.

La lógica final es:

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

Función para determinar si la zona horaria en el 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
fuente
1
De acuerdo con dateandtime.com, el horario de verano comenzó el 10 de marzo de 2019 y, por lo tanto, es en verano, no en invierno, y el desplazamiento del horario de verano de Nueva York es -4, no -5.
jk7
Si es necesario mejorar o corregir la respuesta, realice una edición y se revisará.
Alan Wells
2

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

moment().isDST(); le dará si se observa el ahorro de luz del día.

También tiene una función auxiliar para calcular el tiempo relativo para usted. No necesita hacer cálculos manuales, p. Ej.moment("20200105", "YYYYMMDD").fromNow();

Santhosh S
fuente
1

Estás cerca pero un poco apagado. Nunca necesita calcular su propio tiempo, ya que es el resultado de su propio reloj. Puede detectar si está utilizando el horario de verano en su ubicación, pero no para una ubicación remota producida por el desplazamiento:

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

Esto seguirá siendo incorrecto y apagado una hora si están en horario de verano. Necesita una cuenta de tiempo remota si están actualmente dentro de su horario de verano o no y ajustar en consecuencia. intente calcular esto y cambie su reloj a - digamos 2/1/2015 y reinicie el reloj una hora como si estuviera fuera del horario de verano. Luego calcule para un desplazamiento para un lugar que todavía debería estar 2 horas atrás. Mostrará una hora antes de la ventana de dos horas. Aún necesitaría tener en cuenta la hora y ajustar. Lo hice para Nueva York y Denver y siempre me equivoco (hora por delante) en Denver.

Larry Enzer
fuente
1

Descubrí que usar la biblioteca Moment.js con algunos de los conceptos descritos aquí (en comparación con enero y junio) funciona muy bien.

Esta función simple devolverá si la zona horaria en la que se encuentra el usuario observa el horario de verano:

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

Una manera simple de verificar que esto funcione (en Windows) es cambiar su zona horaria a una zona que no sea DST, por ejemplo, Arizona devolverá falso, mientras que EST o PST devolverán verdadero.

ingrese la descripción de la imagen aquí

Nico Westerdale
fuente
1

Solución a prueba de futuro que funciona en todas las zonas horarias

  1. Sea xel número esperado de milisegundos en el año de interés sin tener en cuenta el horario de verano.
  2. Sea yel número de milisegundos desde la Época desde el comienzo del año de la fecha de interés.
  3. Sea zel número de milisegundos desde la Época de la fecha y hora de interés completas.
  4. Dejar que tsea la resta de ambos xy yde z: z - y - x. Esto produce el desplazamiento debido a DST.
  5. Si tes cero, entonces el horario de verano no está en vigor. Si tno es cero, entonces DST está en 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");
})();

Creo que el fragmento de código anterior es superior a todas las otras respuestas publicadas aquí por muchas razones.

  • Esta respuesta funciona en todas las zonas horarias, incluso en la Antártida / Casey .
  • El horario de verano está muy sujeto a cambios. Puede ser que dentro de 20 años, algún país tenga 3 períodos de DST en lugar de los 2 normales. Este código maneja ese caso al devolver el desplazamiento de DST en milisegundos, no solo si el DST está vigente o no.
  • El tamaño de los meses del año y la forma en que funcionan los años bisiestos encaja perfectamente para mantener nuestro tiempo al día con el sol. Diablos, funciona tan perfectamente que todo lo que hacemos es ajustar unos segundos aquí y allá . Nuestro sistema actual de años bisiestos ha estado en vigencia desde el 24 de febrero de 1582 , y probablemente seguirá en vigencia en el futuro previsible.
  • Este código funciona en zonas horarias que no usan DST.
  • Este código funciona en épocas históricas anteriores a la implementación del horario de verano (como el siglo XX).
  • Este código está optimizado al máximo para enteros y no debería darle ningún problema si se lo llama en un ciclo cerrado. Después de ejecutar el fragmento de código anterior, desplácese hacia abajo hasta la parte inferior de la salida para ver el punto de referencia de rendimiento. Mi computadora puede procesar 16384 fechas en ~ 97 ms en Chrome.

Sin embargo, si no se está preparando para más de 2 períodos de horario de verano, entonces el código siguiente se puede usar para determinar si el horario de verano está en vigor como un valor booleano.

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

Recientemente necesité crear una cadena de fecha con UTC y DST, y en base a la respuesta de Sheldon puse esto junto:

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
fuente
0

¿Hay algún problema al usar el Date.toString().indexOf('Daylight Time') > -1

"" + new Date()

Sáb 01 ene 100050 00:00:00 GMT-0500 (hora estándar del este )

"" + new Date(...)

Dom 01 de mayo 100033 00:00:00 GMT-0400 ( horario de verano)

Esto parece compatible con todos los navegadores.

YC
fuente
Sí, no funciona en todo el mundo. En verano en Europa, obtienes"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
fuente