Pour un petit projet en JavaScript, j'ai eu besoin du numéro de semaine. Par flemme, je suis allé sur Stack Overflow dans l'espoir d'avoir une réponse. Il y en a, en nombre avec des solutions plus ou moins complexe... complexe, mais visiblement pas testé. Je me suis donc mis à écrire ma propre solution... où j'ai eu besoin du numéro de jour dans l'année. Et j'ai eu le même problème, des solutions non testées.
Voyant que mes recherches ne mènent à rien de réellement fonctionnel, n'ayant pas envie de passer par une API juste pour une unique méthode, j'ai posé le problème sur le papier, j'ai regardé comment ça fonctionne et j'ai commencé à écrire ma solution avec quelques cases tests qui ne fonctionnaient pas sur les solutions trouvées. Je me suis d'ailleurs rendu compte qu'il était préférable de ne partir de rien. Le nombre de tests a grandement augmenté quand j'ai eu besoin du numéro de jour de l'année, à cause d'une incohérence dans les calculs quand j'ai testé une année entière... Eh oui, ce foutu changement d'heure d'été, heure d'hiver...
Après avoir résolu tous mes problèmes, voici ma solution... parfaitement fonctionnelle sur mon projet. Je pense ne pas être à l’abri d'un bug. Désolé, je ne mets pas les tests unitaires.
/**
* donne le jour de l'année en prenant en compte le changement d'heure (hiver/été)
* @return jour de l'année (0 à 365~366)
*/
Date.prototype.getDayOfYear = function () {
var date = (new Date(this.getFullYear(), 0, 0));
return Math.floor((this - date - (this.getUTCHours() - date.getUTCHours()) * 3.6e+6) / 8.64e+7);
};
/**
* donne le numéro de semaine
* @param premier premier jour de la semaine (0 = dimanche, 1 = lundi, etc. / défaut = 1)
* @param base numéro de journée maxium pour la première semaine (défaut = 4 : jeudi)
* @return numéro de semaine (1 à 52~53)
*/
Date.prototype.getWeek = function (premier = 1, base = 4) {
premier = typeof(premier) == 'int' ? premier : 1;
base = typeof(base) == 'int' ? base : 4;
var premierAnPre = new Date(this.getFullYear(),0,0);
var dernierAn = new Date(this.getFullYear() +1,0,0);
var jourSemaine = (premierAnPre.getDay() + 7 + premier ) % 7;
var num = Math.ceil( (this.getDayOfYear() + jourSemaine) / 7) + (jourSemaine <= base ? 0 : -1);
if (num == 0) {
num = premierAnPre.getWeek(premier, base);
}
else if (num >= 52 && (dernierAn.getDayOfYear() - this.getDayOfYear()) <= base
&& (dernierAn.getDay() + 7 + premier ) % 7 <= base) {
num = 1;
}
return num;
};
Édit 11/1/2016 : Vous pouvez maintenant retrouver ce code sur ce repository avec une licence GPL :
https://git.ikilote.net/zaide/BakuJS/blob/gh-pages/baku.date.js