Temps : 30min

Qui n'a jamais rêvé d'un beau calendrier sur son site internet ?

On va en cherché vite vite sur internet !!

Mais quel jour tombe la St Valentin en 2025 (un jeudi pour info) ?!?

On prend des scripts déjà fait et ça marche très bien. Il existe pourtant un fait qui titille les codeurs fous (pourquoi vous me regardez tous ?...). Les calendriers et systèmes de dates sont basés sur le temps des machines informatiques. Celles-ci prennent pour la plupart comme référence le Jeudi 1er Janvier 1970. Donc les dates antérieures peuvent aller se gratter. ^^

Cependant il existe ce que l'on appelle des calendriers perpétuels, des algorithmes capables de donner le jour sans avoir de référence initiale (comme le samedi 1er janvier 2000 par exemple).

Durant mes recherches de codes je suis tombé sur ce site internet http://cosmos2000.chez.com/ et plus particulièrement sur cet article : http://cosmos2000.chez.com/Vendredi13/CalendrierArlot.html que je vous invite à lire. Le tableau affiché, que je remet ici, m'a donné envie de le transformer en algorithme que je vais vous présenter. Il est vrai que le site en question propose plusieurs vérificateurs que vous pouvez utiliser pour vérifier vos dates, moi je vous propose un algorithme personnel.

Tableau :

INDICE
ANNÉES

MOISQUANTIÈMES(4)
ou jour
en nombre
(1er au 31)
JOURS
CENTAINESDIZAINESUNITÉS
Cas de
dizaine:
Calendrier
julien(1)
Calendrier
grégorien(2)
PaireImpairePaireImpaire
14   1115 19 23 27 31...2 55Mai1 8 15 22 29Lun.
23   10 610   60Août Fév. B(3)2 9 16 23 30Mar.
32   918 22 26 30 34... 51   71   6Fév. Mars Nov.3 10 17 24 31Mer.
41   8   15 0927Juin4 11 18 25Jeu.
50   7   1417 21 25 29 33...4 3   82   8Sep. Déc.5 12 19 26Ven.
66   13 8393   9Avr. Juil. Jan. B(3)6 13 20 27Sam.
05   1216 20 24 28 32... 744Jan. Oct.7 14 21 28Dim.

(1) Jusqu'au 4 oct. 1582    (2) À partir du 15 oct. 1582; progression annuelle "..." par multiples de 4
(3) Jan. B et Fév. B liés aux années bissextiles (4) Progression par multiples de 7 (jours de semaine)

A présent voyons l'algorithme Javascript complet et commenté s'il vous plait :

3 fonctions obligatoires :

// retourne vrai si l'année est bissextile (surprenant n'est-ce pas ?)
function anneeBissext(a){
    return ( (a % 100 != 0 && a % 4 == 0) || (a % 400 == 0) );
}

// retourne trois caractères possible : 'G'regorien, 'J'ulien, ''aucun
function estJulGreg(siecle, annee, mois, jour){
    var estJul = (siecle <= 15);
    if(siecle == 15){
        estJul = (annee <= 82);
        if(annee == 82){
            estJul = (mois <= 10);
            if(mois == 10){
                estJul = (jour <= 4);
            }
        }
    }

    var estGreg = (siecle >= 15);
    if(siecle == 15){
        estGreg = (annee >= 82);
        if(annee == 82){
            estGreg = (mois >= 10);
            if(mois == 10){
                estGreg = (jour <= 15);
            }
        }
    }

    return (estGreg) ? "G" : ((estJul) ? "J" : "");
}

// http://cosmos2000.chez.com/Vendredi13/CalendrierArlot.html
// Calendrier perpétuel J.E. ARLOT
function calculJour(siecle, annee, mois, jour){

    // le but est de faire une somme d'indice avec le siècle, la dizaine d'année, l'unité d'année
    // le mois et le jour. On déclare donc autant de variables.
    var sommeIndices = 0, indiceS = 0, indiceAD = 0, indiceAU = 0, indiceM = 0, indiceJ = 0;

    // on calcul la dizaine et l'unité d'année
    var dizaineAnnee = Math.floor(annee / 10), uniteAnnee = annee - (dizaineAnnee * 10);

    // l'indice des siècles dépend du type de calendrier
    if(estJulGreg(siecle, annee, mois, jour) == "J"){
        // calendrier Julien
        switch(siecle){
        case 4: case 11: indiceS += 1; break;
        case 3: case 10: indiceS += 2; break;
        case 2: case  9: indiceS += 3; break;
        case 1: case  8: case 15: indiceS += 4; break;
        case 0: case  7: case 14: indiceS += 5; break;
        case 6: case 13: indiceS += 6; break;
        case 5: case 12: indiceS += 0; break;
        }
    }else if(estJulGreg(siecle, annee, mois, jour) == "J"){
        // calendrier Gregorien
        switch((siecle - 15) % 4){
        case 0: indiceS += 1; break;    // siecle 15 19 23 27 31...
        case 1: indiceS += 0; break;    // siecle 16 20 24 28 32...
        case 2: indiceS += 5; break;    // siecle 17 21 25 29 33...
        case 3: indiceS += 3; break;    // siecle 18 22 26 30 34...
        }
    }
    // on vient de traiter les colonnes 2 et 3 du tableau

    // on traite la dizaine d'année
    switch(dizaineAnnee){
    case 0: indiceAD += 4; break;
    case 1: indiceAD += 2; break;
    case 2: indiceAD += 1; break;
    case 3: indiceAD += 6; break;
    case 4: indiceAD += 5; break;
    case 5: indiceAD += 3; break;
    case 6: indiceAD += 2; break;
    case 7: indiceAD += 0; break;
    case 8: indiceAD += 6; break;
    case 9: indiceAD += 4; break;
    }
    // on vient de traiter les colonnes 4 et 5 du tableau

    // on traite l'unité d'année avec la parité de la dizaine d'année
    var pair = (dizaineAnnee % 2 == 0);
    switch(uniteAnnee){
    case 0: indiceAU += 2;    break;
    case 1: indiceAU += 3;    break;
    case 2: indiceAU += (pair) ? 4 : 5;    break;
    case 3: indiceAU += (pair) ? 5 : 6;    break;
    case 4: indiceAU += 0;    break;
    case 5: indiceAU += 1;    break;
    case 6: indiceAU += (pair) ? 2 : 3;    break;
    case 7: indiceAU += (pair) ? 3 : 4;    break;
    case 8: indiceAU += 5;    break;
    case 9: indiceAU += 6;    break;
    }
    // on vient de traiter les colonnes 6 et 7 du tableau

    // on traite le mois avec les années bissextiles ou non
    switch(mois){
    case  1: indiceM += (anneeBissext(siecle * 100 + annee)) ? 6 : 0;    break;
    case  2: indiceM += (anneeBissext(siecle * 100 + annee)) ? 2 : 3;    break;
    case  3: indiceM += 3;    break;
    case  4: indiceM += 6;    break;
    case  5: indiceM += 1;    break;
    case  6: indiceM += 4;    break;
    case  7: indiceM += 6;    break;
    case  8: indiceM += 2;    break;
    case  9: indiceM += 5;    break;
    case 10: indiceM += 0;    break;
    case 11: indiceM += 3;    break;
    case 12: indiceM += 5;    break;
    }
    // on vient de traiter la colonnes 8 du tableau

    // on traite le jour
    indiceJ += (jour % 7 != 0) ? (jour % 7) : 7;
    // il y a un test couplé au modulo pour avoir 7 au lieu de 0
    // car le 0 n'existe pas dans un mois et que nous avons bien le 7, le 14, le 21 et le 28
    // et que faire un modulo 7 ne donnera toujours que : 0, 1, 2, 3, 4, 5, 6

    // on finit faire la somme de tous ces indices et on fait un dernier modulo 7
    sommeIndices = indiceS + indiceAD + indiceAU + indiceM + indiceJ;
    // on obtient un indice de semaine de 0 (Dim.) à 6 (Sam.)
    return sommeIndices % 7;
}

Malgré tout cette fonction ne teste pas la validité de la date, il faut donc la précéder d'une fonction de vérification et en utilisant la fonction "estJulGreg" vous pourrez savoir si la date est dans l'intervalle des quelques jours manquants dans notre calendrier (transition entre Grégorien et Julien).

Donc j'attends vos propositions de scripts à coupler avec mes fonctions pour avoir un beau résultat, mais nan je plaisante.
(Cela dit si vous avez des propositions à faire je suis preneur.)

Ce code étant simple vous pourrez facilement l'adapter à de nombreux langages de programmation.