221 votes

Comment vérifier si l'heure d'été est en vigueur et, le cas échéant, le décalage ?

Voici un bout de mon code JS pour lequel j'ai besoin de ce système :

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

Je veux obtenir la date en "ago", mais si l'heure d'été est utilisée, les dates sont décalées d'une heure. Je ne sais pas comment vérifier si l'heure d'été est en vigueur ou non.

Comment puis-je savoir quand l'heure d'été commence et se termine ?

399voto

Sheldon Griffin Points 1192

Ce code utilise le fait que getTimezoneOffset renvoie un plus grand pendant l'heure normale par rapport à l'heure d'été (DST). Ainsi, il détermine le rendement attendu pendant l'heure normale, et il compare si le rendement de la date donnée est identique (normale) ou inférieur (DST).

Notez que getTimezoneOffset renvoie à positif nombre de minutes pour les zones ouest de l'UTC, qui sont généralement exprimées comme suit négatif heures (puisqu'elles sont "derrière" l'UTC). Par exemple, Los Angeles est UTC-8h Standard, UTC-7h DST. getTimezoneOffset renvoie à 480 (480 minutes positives) en décembre (hiver, heure normale), au lieu de -480 . Il retourne négatif Les chiffres pour l'hémisphère oriental (tels que -600 pour Sydney en hiver, bien que cette ville soit "en avance" ( 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!");
}

36 votes

Je peux vérifier que cela fonctionne au niveau international. Il n'y a actuellement aucun fuseau horaire utilisant une forme quelconque d'heure d'été où le 1er janvier et le 1er juillet sont tous deux dans ou hors de la période d'heure d'été. De plus, dans tous les fuseaux horaires de la TZDB ( avec une exception triviale ) le plus grand des deux décalages est le décalage DST. Puisque l'algorithme JavaScript getTimezoneOffset renvoie la valeur inverse, alors Math.max renvoie en effet le estándar décalage. Le code est correct.

9 votes

Cependant, si un fuseau horaire change de définition de telle sorte que le 1er janvier et le 1er juillet soient tous deux en DST, ou tous deux en DST no en DST (et le DST s'applique toujours), alors ce code ne fonctionnera pas dans cette zone.

12 votes

Cela ne fonctionne pas en général, par exemple, il y a des pays qui n'ont pas observé l'heure d'été certaines années et aussi certains pays inversent l'heure d'été pendant le ramadan. De plus, la définition ECMAScript de la date est défectueuse et la gestion de la variable d'environnement TZ est également défectueuse dans certaines implémentations. Tous ces éléments combinés rendent cette méthode peu fiable. Il est préférable d'utiliser une bibliothèque qui n'utilise pas la date, par exemple timezonecomplete.

64voto

Toastrackenigma Points 55

Cette réponse est assez similaire à la réponse acceptée, mais elle n'annule pas l'obligation d'utiliser l'outil de gestion de l'environnement. Date et n'utilise qu'un seul appel de fonction pour vérifier si l'heure d'été est en vigueur, au lieu de deux.


L'idée est que, puisqu'aucun pays n'observe un DST qui dure sept mois. [1] Dans une région qui observe l'heure d'été, le décalage par rapport à l'heure UTC en janvier sera différent de celui en juillet.

Alors que l'heure d'été déplace les horloges vers l'avant JavaScript renvoie toujours un plus grand pendant l'heure normale. Par conséquent, en obtenant le décalage minimum entre janvier et juillet, on obtient le décalage du fuseau horaire pendant l'heure d'été.

Nous vérifions ensuite si le fuseau horaire de la date est égal à cette valeur minimale. Si c'est le cas, nous sommes en DST, sinon nous ne le sommes pas.

La fonction suivante utilise cet algorithme. Elle prend un objet date, d et retourne true si l'heure d'été est en vigueur pour cette date, et false si ce n'est pas le cas :

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

10 votes

Cela fonctionne, mais s'il n'y a pas de DST dans le fuseau horaire actuel, le résultat sera également vrai, ce qui n'est pas correct. Si vous le changez en Math.max(...) != d.get...() il retournera vrai si l'heure d'été est observée dans le fuseau horaire donné ET si la date est actuellement en heure d'été. Si l'heure d'été n'est pas observée ou si la date correspond au décalage standard, elle renverra false.

3 votes

Il semble que la réponse ait été modifiée pour tenir compte de la correction du commentaire ci-dessus. @Toastrackenigma pouvez-vous confirmer et ajouter une note indiquant que c'est le cas ?

5 votes

Oui, c'était une excellente remarque de @GreySage, et j'ai modifié la réponse pour l'incorporer très rapidement après leur commentaire.

29voto

Jon Nylander Points 4113

Créez deux dates : une en juin, une en janvier. Comparez leurs getTimezoneOffset() valeurs.

  • si le décalage de janvier > décalage de juin, le client est dans l'hémisphère nord
  • si le décalage de janvier est inférieur à celui de juin, le client se trouve dans l'hémisphère sud.
  • si aucune différence, le fuseau horaire du client ne respecte pas l'heure d'été.

Vérifiez maintenant getTimezoneOffset() de la date du jour.

  • si égale à juin, hémisphère nord, alors le fuseau horaire actuel est DST (+1 heure)
  • si égale à janvier, hémisphère sud, alors le fuseau horaire actuel est DST (+1 heure)

1 votes

Pourquoi avez-vous besoin des hémisphères ? Ne serait-il pas suffisant de dire que si getTimezoneOffset() pour la date actuelle est égal au plus petit des deux getTimezoneOffset() alors c'est l'heure d'été ? (et le décalage est la différence entre les deux).

0 votes

Vous n'avez pas besoin des hémisphères comme le démontre clairement la réponse acceptée :)

1 votes

Ça ne marchera pas. La meilleure chose à faire est de s'assurer que vous utilisez les heures UTC et de définir manuellement le décalage pour la région que vous souhaitez. Trouvez ensuite manuellement le début et la fin de l'heure d'été pour la même région (le cas échéant). Vous devez ensuite vérifier si l'heure de cette région se situe dans la plage DST ou non, puis mettre à jour le décalage en conséquence avec +1. Cela permet de comparer les pays qui observent le DST et ceux qui ne le font pas.

14voto

Aaron Cole Points 106

J'ai été confronté à ce même problème aujourd'hui, mais comme notre heure d'été commence et s'arrête à des heures différentes de celles des États-Unis (du moins d'après ce que j'ai compris), j'ai utilisé un itinéraire légèrement différent

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

Il suffit ensuite de comparer le décalage du fuseau horaire actuel avec l'heure d'été et l'heure d'hiver pour voir lequel correspond.

0 votes

C'est ainsi que nous procédons également. Il s'agit de déterminer les périodes de l'année où l'heure d'été change dans votre fuseau horaire cible, et de calculer les décalages pour le jour actuel et la date de changement la plus récente. Ils seront soit différents d'une heure, soit égaux (en supposant que le fuseau horaire en question est décalé d'une heure).

0 votes

Il n'est pas nécessaire de créer 365 valeurs, une approche de recherche binaire qui s'arrête dès qu'un changement de décalage est déterminé devrait être beaucoup plus efficace, même lorsque l'heure d'été n'est pas observée. Toutes ces approches supposent que les lieux observent l'heure d'été chaque année, ce qui n'est pas nécessairement vrai. Les lieux adoptent et abandonnent l'heure d'été de temps en temps (bien que l'ECMAScript suppose que les règles actuelles, quelle que soit leur zone, s'appliquent toujours).

3 votes

Rob - comment pouvez-vous faire cela via une recherche binaire si vous ne savez pas où chercher (c'est-à-dire si l'endroit que vous cherchez se trouve au-dessus ou au-dessous de votre point de test) ?

11voto

Sandy Good Points 1389

El getTimezoneOffset() en JavaScript, dans un navigateur, renvoie le nombre de minutes de décalage par rapport au fuseau horaire 00:00. Par exemple, le fuseau horaire Amérique/New_York en heure d'été (DST) renvoie le nombre 300. 300 minutes représentent un décalage de 5 heures par rapport à zéro. 300 minutes divisées par 60 minutes correspondent à 5 heures. Chaque fuseau horaire est comparé au fuseau horaire zéro, +00:00 / Etc/GMT / Greenwich time.

Docs Web du MDN

La prochaine chose que vous devez savoir, c'est que le décalage a le signe opposé du fuseau horaire réel.

Les informations sur les fuseaux horaires sont gérées par l'Internet Assigned Numbers Authority (iana).

fuseaux horaires de l'iana

Un tableau joliment formaté des fuseaux horaires est fourni par joda.org.

joda-time Fuseaux horaires

+00:00 ou Etc/GMT est l'heure de Greenwich

Tous les fuseaux horaires sont décalés de +00:00 / "Etc/GMT". / heure de Greenwich

En été, l'heure d'été est toujours avancée par rapport à l'heure "normale". Vous réglez vos horloges en arrière à la saison d'automne. (slogan "Fall Back" pour se rappeler ce qu'il faut faire)

Ainsi, l'heure d'Amérique/New_York en heure d'été (hiver) est une heure avant l'heure normale. Ainsi, par exemple, ce qui était normalement 5 heures de l'après-midi dans la ville de New York en été, est maintenant 4 heures de l'heure d'Amérique/New_York en heure d'été. Le nom de l'heure "America/New_York" est un nom de fuseau horaire "Long Format". La côte est des États-Unis appelle généralement son fuseau horaire Eastern Standard Time (EST).

Si vous voulez comparer le décalage horaire d'aujourd'hui à celui d'une autre date, vous devez savoir que le signe mathématique (+/- "positif/négatif") du décalage horaire est l'opposé du fuseau horaire.

Regardez le tableau des fuseaux horaires sur joda.org et trouvez le fuseau horaire pour "America/New_York". Il aura un signe négatif devant le décalage standard.

La terre tourne sur son axe dans le sens inverse des aiguilles d'une montre. Une personne qui observe le lever du soleil à Greenwich voit le lever du soleil 5 heures avant une personne à New York. Et une personne sur la côte ouest des États-Unis verra le lever du soleil après qu'une personne sur la côte est des États-Unis aura vu le lever du soleil.

Il y a une raison pour laquelle vous devez savoir tout ça. Pour que vous puissiez déterminer logiquement si un code JavaScript obtient l'état DST correctement ou non, sans avoir besoin de tester chaque fuseau horaire à différents moments de l'année.

Imaginez que nous sommes en novembre à New York, et que les horloges ont été reculées d'une heure. En été à New York, le décalage est de 240 minutes ou 4 heures.

Vous pouvez tester cela en créant une date qui est en juillet et en obtenant ensuite le décalage.

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

console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

Qu'est-ce qui sera imprimé dans le journal de la console des outils de développement du navigateur ?

La réponse est : 240

Ainsi, vous pouvez maintenant créer une date en janvier et voir ce que votre navigateur retourne pour un décalage de fuseau horaire pour la saison d'hiver.

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 réponse est : 300

Il est évident que 300 est plus grand que 240. Alors, qu'est-ce que cela signifie ? Devriez-vous écrire un code qui teste que le décalage hivernal est plus grand que le décalage estival ? Ou que le décalage d'été est inférieur à celui d'hiver ? S'il y a une différence entre les décalages des fuseaux horaires d'été et d'hiver, alors vous pouvez supposer que l'heure d'été est utilisée pour ce fuseau horaire. Mais cela ne vous dit pas si aujourd'hui utilise l'heure d'été pour le fuseau horaire des navigateurs. Vous devrez donc obtenir le décalage du fuseau horaire pour aujourd'hui.

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

console.log('todaysTimeZone : ' + todaysTimeZone)

La réponse est : ? - Cela dépend de la période de l'année.

Si le décalage du fuseau horaire d'aujourd'hui et le décalage du fuseau horaire d'été sont les mêmes, ET les décalages des fuseaux horaires d'été et d'hiver sont différents, alors par déduction logique, aujourd'hui ne doit PAS être en DST.

Peut-on omettre de comparer les décalages des fuseaux horaires d'été et d'hiver (pour savoir si l'heure d'été est utilisée pour ce fuseau horaire) et se contenter de comparer le décalage du fuseau horaire d'aujourd'hui au décalage du fuseau horaire d'été, et obtenir toujours la bonne réponse ?

today's TZ Offset !== Summer TZ Offset

Aujourd'hui, c'est l'hiver ou l'été ? Si vous le saviez, vous pourriez appliquer la logique suivante :

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

Mais le problème est que vous ne savez pas si la date du jour est en hiver ou en été. Chaque fuseau horaire peut avoir ses propres règles pour le début et la fin de l'heure d'été. Il faudrait suivre les règles de chaque fuseau horaire pour chaque fuseau horaire dans le monde. S'il existe un moyen plus simple et plus efficace, autant le faire de la manière la plus simple et la plus efficace.

Il vous faut donc savoir si ce fuseau horaire utilise l'heure d'été, puis comparer le décalage horaire d'aujourd'hui avec celui d'été. Cela vous donnera toujours une réponse fiable.

La logique finale est :

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

Fonction permettant de déterminer si le fuseau horaire du navigateur utilise l'heure d'été :

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
}

2 votes

Selon dateandtime.com Le DST a commencé le 10 mars en 2019, et se situe donc en été et non en hiver, et le décalage du DST de New York est de -4 et non de -5.

0 votes

Si une amélioration ou une correction doit être apportée à la réponse, veuillez la modifier et elle sera examinée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X