ACCUEIL
EO
| FR
| EN
| |
L'original de cet article est rédigé en
espéranto, langue internationale équitable,
dans laquelle tagnumerilo se décompose ainsi :
Si votre navigateur internet n'autorise pas JavaScript, vous ne pouvez ni voir ni utiliser le numéroteur de jours JavaScript ci-dessous :
Combien de jours séparent deux dates calendaires ?
Quelle date est à tant de jours de telle date ?
Les questions de ce genre semblent plus simples à poser qu'à résoudre, tant les systèmes de calcul du temps, c'est-à-dire les calendriers, paraissent irréguliers et pleins d'exceptions. C'est pourquoi les algorithmes habituels de calendriers perpétuels utilisent des tables pour calculer le numéro de jour de toute date, selon une numérotation séquentielle, à partir de laquelle le problème se réduit à une simple différence arithmétique entre deux numéros de jours.
Cet article présente un
algorithme de numérotation des jours
sans tables,
ainsi que son inverse (du numéro de jour à la date),
pour le calendrier Grégorien en vigueur en occident,
ou son prédécesseur Julien plus simple,
encore utilisable de nos jours sur une période de deux siècles.
Comme les deux algorithmes ne nécessitent qu'une simple
arithmétique entière,
avec seulement des nombres entiers (sans virgule) et des divisions entières
(c'est-à-dire avec un quotient et un reste entiers), ils
conviennent particulièrement aux moyens de calcul simples,
tels le calcul manuel ou les microcontrôleurs les moins chers (et les
plus répandus).
Le globe terrestre fait une révolution autour de son axe pôlaire en
un jour par rapport au soleil, et autour du soleil
en une année par rapport aux étoiles lointaines.
L'angle constant entre ces deux axes de révolution cause les saisons,
avec lesquelles tentent de se synchroniser les calendriers dits
"solaires", tels le Grégorien et le Julien.
La mesure astronomique actuelle
d'une année égale environ 365,2422 jours.
Le calendrier Julien fut institué par
l'empereur romain Julius Cézar
en 45 av. J.-C. sur les conseils d'astronomes égyptiens.
Son année comprend 365 jours, répartis entre les 12 mois actuels,
plus un "jour intercalaire",
ajouté le 29 février chaque
"année bissextile" multiple de quatre.
Cette approximation de la durée de l'année,
en moyenne 365,25 jours,
excellente par rapport aux outils astronomiques de l'époque,
retarde cependant le calendrier Juilen d'environ 3 jours tous les
quatre siècles.
Seize siècles plus tard, pour combler ce retard devenu trop évident,
le calendrier Grégorien fut instauré par
le pape catholique Grégoire XIII en 1582.
D'une part il améliora l'approximation de la durée de l'année,
à en moyenne 365,2425 jours,
en sautant le jour intercalaire de chaque année multiple de 100 mais pas
de 400, c'est-à-dire de 3 jours intercalaires tous les quatre siècles,
et d'autre part il resynchronisa le calendrier par un saut de 10 jours :
le lendemain du jeudi 4/10/1582
fut le vendredi 15/10/1582.
Le changement, du calendrier Julien au Grégorien, ne fut pas immédiatement
accepté par tous les pays : vinrent d'abord les catholiques (par exemple
la France à partir du lundi 20/12/1582), puis plus tard les protestants
(par exemple l'Angleterre à partir du jeudi 14/8/1752), et encore plus tard
les orthodoxes (par exemple la Russie à partir du jeudi 14/2/1918).
Choisissons d'abord le 1er Mars pour origine de la période annuelle
(et donc numérotons janvier=13 et février=14),
à la fin de laquelle se retrouve ainsi reporté l'occasionel jour intercalaire.
Cela fait aussi apparaître une période de 5 mois
de 31+30+31+30+31 = 153 jours :
Les faits du calendrier
Algorithme en entiers sans tables
mois (m) : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
nombre de jours : | 31 | 30 | 31 | 30 | 31 | 31 | 30 | 31 | 30 | 31 | 31 | 28 |
période : | 153 | 153 | ||||||||||
(((m+1)*153)/5)-122 | 0 | 31 | 61 | 92 | 122 | 153 | 184 | 214 | 245 | 275 | 306 | 337 |
Un tantinet d'attention, portée à la suite des multiples de 153/5 et de leurs différences, révèle facilement la formule de la quatrième ligne du tableau, qui égale la somme des nombres de jours des mois compris entre le 1er Mars et le 1er du mois "m" ; ajoutez le quantième du mois de la date pour obtenir le nombre de jours entre le 1er Mars et la date en question.
Entre le 1er Mars d'une année bissextile de base (multiple de 400 pour le calendrier Grégorien, ou de 4 pour le Julien), et le 1er Mars de la "a"-ième année suivante, le nombre de jours est (a*365)+(a/4)-(a/100)+(a/400) pour le calendrier Grégorien (ou plus simplement (a*365)+(a/4) pour le Julien).
Voici donc l'algorithme de numérotation des jours, avec A=année M=mois J=jour, et NG ou NJ = numéro du jour selon le calendrier Grégorien ou Julien :
Pour trouver le jour de la semaine de la date,
diviser N en périodes hebdomadaires de 7 jours (il est remarquable que
la période Grégorienne quadri-séculaire de 146097 jours soit multiple de 7);
le reste de la division euclidienne donne :
reste : | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
Julien (B=0) : | lun | mar | mer | jeu | ven | sam | dim |
Grégorien : | mer | jeu | ven | sam | dim | lun | mar |
Exemple : 3/9/2005, A=2005 M=9 J=3, a=5 m=9, NJ=NG=2012=7*287+3=samedi.
Premièrement, diviser le numéro de jour NG en
périodes quadri-séculaires de 146097 jours :
NG=146097*Q+R (c-à-d Q et R sont
le quotient et le reste de la division euclidienne NG/146097).
Si R=146096, la date est le dernier jour intercalaire
de la période quadri-séculaire,
le 29 février de l'année A=B+Q*400+400.
Sinon, deuxièmement diviser R en périodes séculaires
de 36524 jours : R=36524*C+c.
Les deux premières étapes ne valent que pour le calendrier Grégorien ;
pour le Julien, démarrer ici avec
c=NJ.
Troisièmement diviser c en périodes quadri-annuelles
de 1461 jours : c=1461*q+r.
Si r=1460, la date est un jour intercalaire,
le 29 février de l'année J=B+Q*400+C*100+q*4+4.
Sinon, quatrièmement diviser r en périodes annuelles
de 365 jours : r=365*i+j,
et calculer a=B+Q*400+C*100+q*4+i, et m=(((j+31)*5)/153)+2,
et J=j-(((m+1)*153)/5)+123.
Finalement, si m>12, calculer A=a+1 et M=m-12, sinon A=a et M=m.
La date est A=année M=mois J=jour.
Exemple : NJ=2012, q=1 r=551, i=1 j=186, a=2005 m=9 J=3, A=2005 M=9,
3/9/2005.
D'une part, 16 à 19 siècles d'histoire ont été datés selon le
calendrier Julien. Par exemple, durant la vie de Zamenhof
(concepteur de la langue internationale équitable Espéranto),
les russes utilisaient encore le calendrier Julien
(jusqu'à son mercredi 31 janvier 1918, qui était le 13 février Grégorien),
alors 13 jours en retard sur le Grégorien, utilisé par les occidentaux
depuis déjà trois siècles.
D'autre part, les microcontrôleurs calculent plus économiquement avec
des nombres de 16 bits, entre 0 et 65535, soit le nombre de jours d'environ
180 ans.
Comme entre le 1/3/1900 et le 28/2/2100
les années bissextiles Grégoriennes et Juliennes coincident,
on peut utiliser l'algorithme Julien plus simple, avec par exemple
l'an 1900 pour base (1/3/1900 = jour numéro 0, jusqu'au
jour numéro 65535 = 5/5/2079).
Algorithme inverse
Usages de l'algorithme Julien
Codages
static int gregorien = 1; // 1:Gregorien 0:Julien
typedef struct{int jour, mois, an;} date; // 1..31, 1..12, ..2005..
int numerojour(date d) { // convertit date en numero de jour
if(mois<3){ d.an-=1; d.mois+=12; } // decaler origine au 1er mars
return d.an*365 + d.an/4 + (gregorien ? -d.an/100 + d.an/400 : 0)
+ (d.mois+1)*153/5-123 + d.jour;
}
int joursemaine(int n) { // convertit numero de jour en :
return (gregorien ? n+2 : n) % 7; // 0=lundi .. 6=dimanche
}
void datejour(int n, date *d) { // convertit numero de jour en date
int m, a=0;
if(gregorien) {
m = n/146097; a += m*400; n -= m*146097; // periodes 400 ans
if(n==146096) { d->an=a+400; d->mois=2; d->jour=29; return; }
m = n/36524; a += m*100; n -= m*36524; // periodes 100 ans
}
m = n/1461; a += m*4; n -= m*1461; // periodes 4 ans
if(n==1460) { d->an=a+4; d->mois=2; d->jour=29; return; }
m = n/365; a += m; n -= m*365; // periodes 1 an
m = (n+31)*5/153+2; n -= (m+1)*153/5-123;
if(m>12) { a+=1; m-=12; } // recaler origine au 1er janvier
d->an=a; d->mois=m; d->jour=n; return;
}
1 value gregorien \ 1:Gregorien 0:Julien
: date> \ j m a -- n ; convertit date j/m/a en numero du jour n
>r dup 3 < IF 12 + r> 1- >r THEN \ decaler origine au 1er mars
1+ 153 * 5 / 123 - + \ -- n | a ; n jours du 1/3/a au j/m/a
r@ 4 / + gregorien IF r@ 100 / - r@ 400 / + THEN r> 365 * +
;
: >jsem \ n -- s ; convertit numero de jour n en :
gregorien IF 2 + THEN 7 mod \ 0:lundi .. 6:dimanche
;
: >date \ n -- j m a ; convertit numero de jour n en date j/m/a
0 >r gregorien IF
146097 /mod 400 * r> + >r \ periodes 400 ans
146096 over = IF drop 29 2 r> 400 + exit THEN
36524 /mod 100 * r> + >r \ periodes 100 ans
THEN \ -- n | a
1461 /mod 4 * r> + >r \ periodes 4 ans
1460 over = IF drop 29 2 r> 4 + exit THEN
365 /mod r> + >r \ periodes 1 an
dup 31 + 5 * 153 / 2 + tuck 1+ 153 * 5 / 123 - - swap \ -- j m | a
dup 12 > IF 12 - r> 1+ >r THEN r> \ -- j m a
;
Liens
CL20080702