Comment utiliser JavaScript pour calculer le jour de l'année, de 1 à 366 ?
Par exemple :
-
January 3
devrait être3
. -
February 1
devrait être32
.
Comment utiliser JavaScript pour calculer le jour de l'année, de 1 à 366 ?
Par exemple :
January 3
devrait être 3
.February 1
devrait être 32
.Suite à l'édition de l'OP :
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = now - start;
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);
Edit : Le code ci-dessus échouera quand now
est une date comprise entre le 26 mars et le 29 octobre et now
L'heure de l'utilisateur est antérieure à 1 heure du matin (par exemple 00:59:59). Cela est dû au fait que le code ne tient pas compte de l'heure d'été. Vous devez compenser pour ça :
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);
Je trouve très intéressant que personne n'ait envisagé d'utiliser l'UTC puisqu'il n'est pas soumis à l'heure d'été. Par conséquent, je propose ce qui suit :
function daysIntoYear(date){
return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
}
Vous pouvez le tester avec les éléments suivants :
[new Date(2016,0,1), new Date(2016,1,1), new Date(2016,2,1), new Date(2016,5,1), new Date(2016,11,31)]
.forEach(d =>
console.log(`${d.toLocaleDateString()} is ${daysIntoYear(d)} days into the year`));
Quelles sorties pour l'année bissextile 2016 (vérifié à l'aide de http://www.epochconverter.com/days/2016 ):
1/1/2016 is 1 days into the year
2/1/2016 is 32 days into the year
3/1/2016 is 61 days into the year
6/1/2016 is 153 days into the year
12/31/2016 is 366 days into the year
Ce système fonctionne pour tous les changements d'heure d'été dans tous les pays (le système "noon" ci-dessus ne fonctionne pas en Australie) :
Date.prototype.isLeapYear = function() {
var year = this.getFullYear();
if((year & 3) != 0) return false;
return ((year % 100) != 0 || (year % 400) == 0);
};
// Get Day of Year
Date.prototype.getDOY = function() {
var dayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
var mn = this.getMonth();
var dn = this.getDate();
var dayOfYear = dayCount[mn] + dn;
if(mn > 1 && this.isLeapYear()) dayOfYear++;
return dayOfYear;
};
Heureusement, cette question ne précise pas si le numéro de la actuel jour est nécessaire, ce qui laisse de la place pour cette réponse.
De plus, certaines réponses (également sur d'autres questions) avaient des problèmes d'années bissextiles ou utilisaient l'objet Date. Bien que la fonction Date object
couvre environ 285616 ans (100 000 000 jours) de part et d'autre du 1er janvier 1970, j'en avais assez de toutes sortes de dates inattendues incohérences à travers les différents navigateurs (plus particulièrement de l'année 0 à 99). J'étais également curieux de savoir comment le calculer.
J'ai donc écrit un texte simple et surtout, petit pour calculer le correct ( Proleptique Grégorien / Astronomique / ISO 8601:2004 (clause 4.3.2.1), donc année 0
existe et est une année bissextile et les années négatives sont prises en charge ) jour de l'année sur la base de année , mois y jour .
Notez que dans AD/BC
l'année 0 AD/BC n'existe pas : au lieu de cela, l'année 1 BC
est l'année bissextile ! Si vous devez tenir compte de la notation BC, il suffit de soustraire une année de la valeur de l'année (autrement positive) en premier lieu !
J'ai modifié (pour javascript) le algorithme du masque binaire à court-circuit - modulo leapYear et j'ai trouvé un nombre magique pour faire une recherche rapide de offsets (qui exclut jan et feb, nécessitant ainsi 10 * 3 bits (30 bits étant inférieurs à 31 bits, nous pouvons sans risque enregistrer un autre caractère sur le décalage de bits au lieu de >>>
)).
Notez que ni le mois ni le jour ne peuvent être 0
. Cela signifie que si vous avez besoin de cette équation juste pour la actuel jour (en le nourrissant avec .getMonth()
), il suffit de supprimer le --
de --m
.
Notez que cela suppose une date valide (bien que la vérification d'erreur soit juste quelques caractères de plus).
function dayNo(y,m,d){
return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>
<br><hr><br>
<button onclick="
var d=new Date();
this.nextSibling.innerHTML=dayNo(d.getFullYear(), d.getMonth()+1, d.getDate()) + ' Day(s)';
">get current dayno:</button><span></span>
Voici la version avec correct validation de la gamme.
function dayNo(y,m,d){
return --m>=0 && m<12 && d>0 && d<29+(
4*(y=y&3||!(y%25)&&y&15?0:1)+15662003>>m*2&3
) && m*31-(m>1?(1054267675>>m*3-6&7)-y:0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>
Encore une fois, une seule ligne, mais je l'ai divisée en 3 lignes pour la lisibilité (et l'explication suivante).
La dernière ligne est identique à la fonction ci-dessus, mais l'algorithme (identique) de l'année bissextile est déplacé dans une section précédente de court-circuit (avant le calcul du nombre de jours), car il est également nécessaire pour savoir combien de jours compte un mois dans une année (bissextile) donnée.
La ligne du milieu calcule la valeur correcte décalage (pour le nombre maximum de jours) pour un mois donné dans une année (bissextile) donnée en utilisant un autre nombre magique : depuis 31-28=3
y 3
n'est que de 2 bits, alors 12*2=24
bits, nous pouvons stocker les 12 mois. Comme l'addition peut être plus rapide que la soustraction, nous ajoutons le décalage (au lieu de le soustraire de 31
). Pour éviter une décision de l'année bissextile pour février, nous modifions ce numéro de référence magique à la volée.
Il nous reste donc la première ligne (assez évidente) : elle vérifie que le mois et la date sont dans des limites valides et nous assure avec un false
valeur de retour en cas d'erreur de gamme (notez que cette fonction ne devrait pas non plus pouvoir retourner 0, car 1 jan 0000 est toujours le jour 1.), ce qui permet de vérifier facilement les erreurs : if(r=dayNo(/*y, m, d*/)){}
.
Si elle est utilisée de cette façon (où le mois et le jour ne sont pas nécessairement 0
), alors on peut changer --m>=0 && m<12
à m>0 && --m<12
(sauvegarde d'une autre image).
La raison pour laquelle j'ai tapé l'extrait dans sa forme actuelle est que pour les valeurs mensuelles basées sur 0, il suffit de supprimer l'attribut "0". --
de --m
.
Extra :
Remarque : n'utilisez pas cet algorithme de jours par mois si vous n'avez besoin que du nombre maximal de jours par mois. Dans ce cas, il existe un algorithme plus efficace (car nous n'avons besoin de leepYear que lorsque le mois est février) que j'ai posté en réponse à cette question : Quelle est la meilleure façon de déterminer le nombre de jours dans un mois avec javascript ? .
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.
4 votes
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;
0 votes
Mais vraiment, je ne suis pas sûr de ce que vous voulez dire. Vous voulez juste le nombre de jours dans l'année ? Ou entre deux dates ?
20 votes
Fyi @xeon06, le calcul des années bissextiles est un peu plus compliqué que de moduler par 4. voir : algorithme des années bissextiles
4 votes
@Xeon06 : C'est correct seulement la plupart du temps. De Wikipedia : Les années divisibles par 100 ne sont pas bissextiles, à moins qu'elles ne soient également divisibles par 400. sont les années bissextiles.
0 votes
Ah bien, je me suis trompé. @minitech semble avoir la bonne réponse alors.
0 votes
Désolé Xeon06, je veux obtenir le cumul annuel.
0 votes
@Sophia Ok, j'ai mis à jour ma réponse :)
0 votes
Je ne peux pas croire qu'il n'existe pas une fonction existante sur l'objet Date pour cela.