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 ?

9voto

Jack Giffin Points 1

Une solution à l'épreuve du temps qui fonctionne dans tous les fuseaux horaires

  1. Soit x est le nombre de millisecondes prévu dans l'année concernée sans tenir compte de l'heure d'été.
  2. Soit y être le nombre de millisecondes depuis que la Epoch à partir du début de l'année de la date de l'intérêt.
  3. Soit z être le nombre de millisecondes depuis que la Epoch de la date et de l'heure complètes de l'intérêt
  4. Soit t soit la soustraction des deux x y y de z : z - y - x . On obtient ainsi le décalage dû à l'heure d'été.
  5. Si t est égal à zéro, alors l'heure d'été n'est pas en vigueur. Si t n'est pas zéro, alors l'heure d'été est en vigueur.

    "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)) // 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) -1 + // first day in the year is day 1 (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");

Je pense que l'extrait de code ci-dessus est supérieur à toutes les autres réponses postées ici pour de nombreuses raisons.

  • Cette réponse fonctionne dans tous les fuseaux horaires, même Antarctique/Casey .
  • L'heure d'été est très susceptible de changer. Il se peut que dans 20 ans, un pays ait 3 périodes d'heure d'été au lieu des 2 habituelles. Ce code gère ce cas en retournant le décalage DST en millisecondes, et pas seulement le fait que le DST soit en vigueur ou non.
  • La taille des mois de l'année et la façon dont fonctionnent les années bissextiles s'intègrent parfaitement à la synchronisation de notre temps avec le soleil. Cela fonctionne si bien que tout ce que nous faisons, c'est juste d'ajustement de quelques secondes ici et là . Notre système actuel d'années bissextiles est en vigueur depuis le 24 février 1582 et restera probablement en vigueur dans un avenir prévisible.
  • Ce code fonctionne dans les fuseaux horaires qui n'utilisent pas l'heure d'été.
  • Ce code fonctionne dans les périodes historiques antérieures à la mise en place de l'heure d'été (comme les années 1900).
  • Ce code est optimisé au maximum pour les entiers et ne devrait pas vous poser de problème s'il est appelé dans une boucle serrée. Après avoir exécuté l'extrait de code ci-dessus, faites défiler jusqu'au bas de la sortie pour voir l'évaluation des performances. Mon ordinateur est capable de traiter 16384 dates en 29ms sur FireFox.

Toutefois, si vous ne vous préparez pas pour plus de 2 périodes de DST, le code ci-dessous peut être utilisé pour déterminer si le DST est en vigueur comme un booléen.

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

9voto

epeleg Points 2346

Sur la base du commentaire de Matt Johanson sur la solution fournie par Sheldon Griffin, j'ai créé le code suivant :

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

Il essaie d'obtenir le meilleur de tous les mondes en tenant compte de tous les commentaires et des réponses suggérées précédemment et en le précisant :

1) Met en cache le résultat de l'année stdTimezoneOffset afin que vous n'ayez pas besoin de le recalculer lorsque vous testez plusieurs dates de la même année.

2) Il ne suppose pas que l'heure d'été (si elle existe) soit nécessairement en juillet, et fonctionnera même si, à un moment donné et à un endroit donné, il s'agit de n'importe quel mois. Cependant, du point de vue des performances, il fonctionnera plus rapidement si le mois de juillet (ou les mois voisins) est effectivement l'heure d'été.

3) Dans le pire des cas, il comparera le getTimezoneOffset du premier de chaque mois. [et faire cela une fois par année testée].

L'hypothèse qu'il fait toujours est que la période de l'heure d'été est plus grande qu'un seul mois.

Si quelqu'un veut supprimer cette hypothèse, il peut changer la boucle en quelque chose qui ressemble davantage à la solution fournie par Aaron Cole - mais je continuerais à sauter une demi-année en avant et à sortir de la boucle lorsque deux décalages différents sont trouvés].

4voto

Daniel F. Points 836

El moment.js La bibliothèque fournit un .isDst() sur ses objets temporels.

moment#isDST vérifie si le moment actuel est en heure d'été.

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

0 votes

J'ai essayé var moment = require('moment') ; this.logger.info(moment([2011, 2, 12]).isDST()) ; this.logger.info(moment([2011, 2, 14]).isDST()) ; les deux sont faux.

0 votes

Les dates de changement d'heure varient selon les pays. pays Même parmi les États d'un même pays (par exemple, l'État de l'Arizona). Aux États-Unis, la date est le 13 mars 2011, tandis qu'en Allemagne, elle est le 31 mars 2011. Le résultat sera donc différent selon le fuseau horaire dans lequel moment.js est configuré pour fonctionner.

1 votes

Il varie même à l'intérieur de l'état d'Arizona. timeanddate.com/time/us/arizona-no-dst.html

2voto

Nico Westerdale Points 345

J'ai découvert qu'en utilisant le Moment.js avec certains des concepts décrits ici (comparaison entre janvier et juin) fonctionne très bien.

Cette fonction simple indique si le fuseau horaire dans lequel se trouve l'utilisateur observe l'heure d'été :

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

Une façon simple de vérifier que cela fonctionne (sous Windows) est de changer votre fuseau horaire pour une zone non DST, par exemple Arizona retournera false, alors que EST ou PST retourneront true.

enter image description here

2voto

Santhosh S Points 310

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

moment().isDST(); vous donnera si l'heure d'été est respectée.

Il dispose également d'une fonction d'aide pour calculer le temps relatif pour vous. Vous n'avez pas besoin de faire des calculs manuels par exemple moment("20200105", "YYYYMMDD").fromNow();

1 votes

Avez-vous remarqué que la réponse "Utiliser Moment.js" était déjà donné en 2017 ?

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