UN CALENDRIER PERPETUEL POUR VOTRE MICRO


Voila un calendrier qui va vous aider à vous rafraîchir la mémoire. Il va vous permettre aussi bien de marquer les grands événements historiques, que de prévoir des événements futurs importants. Pour vous aider, il vous indique même les jours fériés et fêtes religieuses. C'est une bonne occasion de prévoir vos vacances à long terme !


Un peu d'histoire

Remontons en l'an 1582 : depuis cette année nous vivons sous le règne du calendrier grégorien, qui a fait place au calendrier julien. Il en fut décidé ainsi par le pape Grégoire XIII afin de rattraper l'avance prise par l'ancien calendrier et se rapprocher le plus du temps séparant deux passages consécutifs du soleil au tropique (365,24220 jours contre 365,2425 jours pour le calendrier grégorien et 365,25 jours dans le système julien).

Mais le calcul du nombre de jours selon le calendrier julien reste une convention astronomique pour le calcul des durées selon un temps universel. Ce nombre magique est en fait la base de notre calendrier perpétuel.

Le nombre de jour julien :

En effet, le calcul de nombre pour une date donnée permet d'en déduire très simplement le jour de la semaine mais également le nombre de jours qui la sépare d'une autre date :

  • Le calcul du jour de la semaine d'une date se fait simplement en divisant ce nombre par 7. Le reste de la division représente le jour de la semaine : 0 pour dimanche, 1 pour lundi ...
  • Le nombre de jour entre deux dates se fait par différence des deux nombres de jours julien des dates.

En théorie, ce nombre représente le nombre de jour écoulé depuis le commencement de la période julienne qui est situé au 1er janvier de l'année 4712 av. J-C. En pratique, on préfère la date julienne modifiée, obtenue en retranchant 2 400 000 à la date julienne, ce qui est beaucoup plus digeste pour notre micro !

Le calcul du jour julien modifié implémenté dans notre programme n'est valable que pour les dates du système grégorien.

Déterminer la date de pâques :

Maintenant que nous savons calculer le nombre de jours dans l'année où se situe une date, nous pouvons associer chaque jour à un événement particulier. Nous allons par exemple indiquer les fêtes importantes de l'année.

Pour les fêtes de dates fixes, tels que Noël ou le Nouvel An, il est facile de déterminer le nombre de jours dans l'année où elles se situent. Mais comment savoir où se situent les fêtes religieuses mobiles telles que l'ascension ?

Heureusement pour nous, les fêtes mobiles religieuses se déterminent toutes à partir de la date de Pâques. Voici donc une méthode pour déterminer la date de Pâques.

Par définition, Pâques se situe le premier dimanche après la première pleine lune de printemps, entre le 21 mars et le 25 avril.

L'astronome anglais Spencer Jones a développé en 1922 une méthode numérique de la date de Pâques à partir de formules établies un demi siècle avant par des ecclésiastiques.

Concrètement cette méthode consiste à effectuer neuf divisions en chaîne à partir de l'année en cours et à garder soit la partie entière, soit le reste de la division. Seul l'année est nécessaire pour calculer cette date, mais il faut mobiliser pas moins de douze variables pour calculer cette date.

Les dates du carême, des Rameaux, de la Pentecôte, de l'Ascension et de la Fête-Dieu se situent respectivement à - 42 jours, - 7 jours, + 49 jours, + 39 jours et à 60 jours de celle de Pâques.

Il faut savoir de plus qu'en France, depuis le Concordat de 1802, de toutes les fêtes religieuses qui ne tombent pas un dimanche, quatre seulement sont chômées : Noël (25 dec.), l'Ascension, l'Assomption (15 Août) et la Toussaint (1er Nov.). Les autres tel que l'épiphanie (6 janv.), ou la Fête-Dieu, sont reportés au dimanche suivant. Il en est de même pour la fête Jeanne d'Arc (8 mai).

Ces fêtes sont les événements par défaut de notre calendrier. Mais cela n'aurait pas d'intérêt si nous ne pouvions pas créer nous mêmes nos propres événements (dates d'anniversaire, taches importantes à faire ...).

Le fichier des événements :

Les événements sont sauvés sur disque, par années, seulement si cela est nécessaire. Ils sont écrit dans le fichier de type Text les uns après les autres. Chaque ligne du fichier représente une date. Si un jour ne contient pas d'événement important, une ligne vide y est écrite.

La gestion de ces fichiers se fait de la manière suivante : Un fichier annuel des événements est créé ou modifié dés qu'un événement a été ajouté ou modifié dans l'année.

A chaque passage à une nouvelle année, le fichier est sauvé si besoin ait, et le fichier de la nouvelle année est lu. Si le fichier n'existe pas, les événements de l'année sont initialisés par défaut.

Cette méthode permet ainsi de ne pas surcharger votre disque de fichiers d'événements.

Mode d'emploi du programme :

Le programme a été écrit pour Turbo Pascal version 4 et supérieure. Le calendrier est affiché en mode graphique 640x350 16 couleurs. Il faut donc au moins une carte graphique EGA pour l'exécuter.

La date d'aujourd'hui est affichée en verte, les dates passées en grises (elles ont été barrées), et les dates futures en noirs.

La date en cours est affiché en rouge. Elle peut être déplacée à l'aide des touches fléchés de votre clavier. Pour créer ou modifier un événement d'une date, déplacez-vous sur la date et tapez sur la touche Entrée. Tapez l'événement puis validez en retapant sur la touche Entrée.

Utilisez les touches PgDw et PgUp pour passer au mois suivant ou précédent, Ctrl-PgDw et Ctrl-PgUp pour passer à l'année suivante ou précédente. La touche Ctrl-Entrée permet de revenir sur la date d'aujourd'hui.

Enfin utilisez l'option /A dans la ligne de commande pour afficher les événements importants d'aujourd'hui et de demain. Cette option peut être insérée dans votre fichier AUTOEXEC.BAT pour vous indiquer au jour le jour les événements importants à venir. Vous n'aurez plus aucune excuse d'avoir oublié une date d'anniversaire !

Listing du programme en Turbo-Pascal :

(*
 *                          CALENDRIER PERPETUEL
 *
 *       Copyright (c) 1993 par Frédéric HARDY pour Réponse Micro
 *)
 
Program CALenDrier;
 
Uses Graph, Crt, Dos;
 
Const
 
  NbrMaxJours = 367;
 
  TabJours : Array [0..6] of char = ('D','L','M','M','J','V','S');
  TabMois : Array[1..12] of String[20] = ('Janvier','Février','Mars','Avril',
            'Mai','Juin','Juillet','Aout','Septembre','Octobre','Novembre',
            'Décembre');
 
Type
 
  RemStr = String[28];
  CoordXY = Record x,y : Word; end;
 
Var EvtDuJour : Array [0..NbrMaxJours] of RemStr;
    TabXY     : Array [1..31] of CoordXY;
    NomFAnnee : PathStr;
 
(*
 *  Gestionnaire et fonte graphique
 *)
 
Procedure EGAVGADriver; External;
{$L EGAVGA.OBJ}
 
Procedure SansSerifFont; External;
{$L SANS.OBJ}
 
(*
 *  Initialisation du mode graphique
 *)
 
Procedure InitGraph;
 
Var  gd,gm : integer;
 
Begin
  { Initialisation du gestionnaire et de la fonte graphique }
  if (RegisterBGIDriver(@EGAVGADriver)<0) or
    (RegisterBGIFont(@SansSerifFont)<0)
  then
  Begin
    WriteLn('Erreur fatale!');
    Halt(1);
  end;
  { Ecran graphique 640x350 16 couleurs }
  gd := EGA;    { ou VGA }
  gm := EGAhi;  { ou VGAMed }
  Graph.InitGraph(gd,gm,'');
  { Affichage du décor }
  SetFillStyle(SolidFill,LightGray);
  Bar(0,0,GetMaxX,GetMaxY);
  SetLineStyle(SolidLn,0,3);
  SetColor(DarkGray);
  Line(0,1,GetMaxX,1);
  Line(GetMaxX-1,0,GetMaxX-1,GetMaxY);
  SetColor(White);
  Line(0,GetMaxY-1,GetMaxX-2,GetMaxY-1);
  Line(1,2,1,GetMaxY);
end;
 
(*
 *  Bip sonore en cas de mauvaise action
 *)
 
Procedure Bip;
 
Begin
  Sound(100);
  Delay(100);
  NoSound;
end;
 
(*
 *  Signal sonore pour annoncer un événement
 *)
 
Procedure DingDong;
 
Begin
  Sound(100);
  Delay(100);
  Sound(200);
  Delay(100);
  NoSound;
end;
 
(*
 *  Calcule le nombre de jour selon le calendrier julien
 *)
 
Function CalcNbrJour(J,M,A : Word) : Word;
 
Var Na : Real;
 
Begin
  IF (M<3) Then
  Begin
    Na := (A-1)/100;
    CalcNbrJour := 365*A+J+31*(M-1)+Trunc(Na*25)-Trunc(3/4*(Int(Na)+1));
  end
  else
    CalcNbrJour := 365*A+J+31*(M-1)-Trunc(0.4*M+2.3)+Trunc(A/4)-Trunc(3/4*(Int(A/100)+1));
end;
 
(*
 *  Calcul le nombre de jour depuis le debut de l'année
 *)
 
Function NbJour(J, M, A : Word) : Word;
 
Begin
  NbJour := CalcNbrJour(J,M,A)-CalcNbrJour(1,1,A);
end;
 
(*
 *  Nombre de jour dans l'annee
 *)
 
Function NbJourAnnee(Annee : Word) : Word;
 
Begin
  NbJourAnnee := CalcNbrJour(1,1,Annee+1) - CalcNbrJour(1,1,Annee);
end;
 
(*
 *  Calcul de la date de pâques selon la méthode de Spender Jones
 *)
 
Function CalculPaques(Annee : Word) : Integer;
 
Var R01, R02, R03, R04, R05, R06,
    R07, R08, R09, R10, R11, R12 : Integer;
 
Begin
  R01 := Annee mod 19;
  R02 := Annee div 100;
  R03 := Annee mod 100;
  R04 := R02 div 4;
  R05 := R02 mod 4;
  R06 := (8+R02) div 25;
  R07 := (1+R02-R06) div 3;
  R08 := 15+19*R01+R02-R04-R07;
  R08 := R08 mod 30;
  R09 := R03 div 4;
  R10 := R03 mod 4;
  R11 := 32+2*(R05+R09)-R08-R10;
  R11 := R11 mod 7;
  R12 := (R01+11*R08+22*R11) div 451;
  CalculPaques := NbJour(21,3,Annee)+R08+R11-7*R12+1;
end;
 
(*
 *  Ecrit les événements d'une l'année sur fichier
 *)
 
Procedure EcritFich(Annee : Word);
 
Var i : word;
    f : text;
 
Begin
  Assign(f,NomFAnnee);
  ReWrite(f);
  For i:=0 to NbJourAnnee(Annee)-1 do WriteLn(f,EvtDuJour[i]);
  close(f);
end;
 
(*
 *  Initialise ou lit sur fichier les événements d'une nouvelle année
 *)
 
Procedure InitNouvAnnee(Annee : Word);
 
Var i : word;
    Paques : Integer;
    St : String[5];
    f : text;
 
Begin
  { Recherche du fichier de l'année en cours }
  Str(Annee,St);
  NomFAnnee := FSearch(St + '.CLD',GetEnv('PATH'));
  { Cas  il n'y a pas de fichier ... }
  if (NomFAnnee='') then
  begin
    NomFAnnee := St + '.CLD';
    For i:=0 to NbrMaxJours Do EvtDuJour[i]:='';
    EvtDuJour[0]:='NOUVEL AN';
    EvtDuJour[7-(CalcNbrJour(1,1,Annee) mod 7)] := 'EPIPHANIE';
    EvtDuJour[NbJour(1,5,Annee)]:='FETE DU TRAVAIL';
    EvtDuJour[NbJour(8,5,Annee)]:='VICTOIRE 1945';
    i := 7-(CalcNbrJour(8,5,Annee) mod 7);
    If (i=7) then i:=0;
    EvtDuJour[NbJour(8,5,Annee)+i] := 'FETE JEANNE-D''ARC';
    EvtDuJour[NbJour(14,7,Annee)]:='FETE NATIONALE';
    EvtDuJour[NbJour(15,8,Annee)]:='ASSOMPTION';
    EvtDuJour[NbJour(1,11,Annee)]:='TOUSSAINT';
    EvtDuJour[NbJour(11,11,Annee)]:='ARMISTICE 1918';
    EvtDuJour[NbJour(25,12,Annee)]:='NOEL';
    Paques := CalculPaques(Annee);
    EvtDuJour[Paques-42] := 'CAREME';
    EvtDuJour[Paques-7] := 'RAMEAUX';
    EvtDuJour[Paques] := 'PAQUES';
    EvtDuJour[Paques+1] := 'LUNDI DE PAQUES';
    EvtDuJour[Paques+39]:='ASCENSION';
    EvtDuJour[Paques+49]:='PENTECOTE';
    EvtDuJour[Paques+50]:='LUNDI DE LA PENTECOTE';
    EvtDuJour[Paques+63]:='FETE-DIEU';
  end
  { ... sinon lecture du fichier }
  else
  Begin
    assign(f,NomFAnnee);
    reset(f);
    for i:=0 to NbJourAnnee(Annee)-1 do ReadLn(f,EvtDuJour[i]);
    close(f);
  end;
end;
 
(*
 *  Affiche l'evenement du jour dans le calendrier
 *)
 
Procedure AffichJour(J,M,A : Word; Co : Byte);
 
Var St : String[5];
    JS : Word;
 
Begin
  Str(J:3,st);
  SetColor(Co);
  JS := CalcNbrJour(J,M,A) mod 7;
  OutTextXY(TabXY[J].x,TabXY[J].y,TabJours[JS]+st+'  '+EvtDuJour[NbJour(J,M,A)]);
end;
 
(*
 *  Modifie l'evenement du jour
 *)
 
Function ChangeRem(J,M,A : Word) : Boolean;
 
Var Change : Boolean;
    px,py : Word;
    St : RemStr;
    it,i : Word;
    ch : Char;
 
Begin
  it := NbJour(J,M,A);
  St := EvtDuJour[it];
  Change := False;
  px:= TabXY[j].x + (Length(EvtDuJour[it])+6)*8;
  py:= TabXY[j].y;
  repeat
    SetColor(Cyan);
    OutTextXY(px,py,#219);
    ch := ReadKey;
    case ch of
      #00 : Ch := Readkey;
      #08 : If (Length(St)>0) then   { BackSpace }
            Begin
              Delete(St,Length(St),1);
              SetColor(LightGray);
              OutTextXY(px,py,#219);
              Dec(px,8);
              Change := True;
            end
            else Bip;
      #127 : If (Length(St)>0) then  { Ctrl-BackSpace }
             Begin
               SetColor(LightGray);
               For i:=1 to Length(St) do
               Begin
                 OutTextXY(px,py,#219);
                 Dec(px,8);
               end;
               St := '';
               Change := True;
             end
             else Bip;
      #32..#126,
      #128..#255 : If (Length(St)<28) then
                  Begin
                    St := St + Ch;
                    SetColor(LightGray);
                    OutTextXY(px,py,#219);
                    SetColor(Red);
                    OutTextXY(px,py,ch);
                    Inc(px,8);
                    Change:=True;
                  end
                  else Bip;
    end;
  until (ch=#13) or (ch=#27);
  SetColor(LightGray);
  OutTextXY(px,py,#219);
  If (Ch=#27) then
  Begin
    for i:=1 to Length(St) do
    Begin
      Dec(px,8);
      OutTextXY(px,py,#219);
    end;
    AffichJour(j,m,a,Red);
    Change := False;
  end
  else
    EvtDuJour[it]:=St;
  ChangeRem := Change;
end;
 
(*
 *  Affiche le calendrier
 *)
 
Procedure AffCalendrier;
 
var i : byte;
    St : String[25];
    px, py : Word;
    Annee, Mois, Jour, JourSem, NbrJourMois : Word;
    Aujourdhui, JourEnCours : Word;
    Sortie, ChangeMois, RAZ, ChangeFich : Boolean;
    Co : Byte;
    ch : Char;
 
Begin
  Sortie := False;
  ChangeFich:=False;
  Repeat
  RAZ := False;
  GetDate(Annee,Mois,Jour,JourSem);
  Aujourdhui := CalcNbrJour(Jour,Mois,Annee);
  InitNouvAnnee(Annee);
  Repeat
    { Affichage du cadre }
    SetFillStyle(SolidFill,LightGray);
    Bar(3,3,GetMaxX-3,GetMaxY-3);
    { Affichage du mois et de l'année en cours en relief }
    SetTextJustify(CenterText,CenterText);
    SetTextStyle(Graph.SansSerifFont,HorizDir,4);
    Str(Annee:5,St);
    St := TabMois[Mois] + St;
    SetColor(Brown);
    OutTextXY(320,15,St);
    SetColor(Yellow);
    OutTextXY(321,16,St);
    SetTextJustify(LeftText,CenterText);
    SetTextStyle(DefaultFont,HorizDir,1);
    { Calcul du nombre de jour dans le mois }
    if Mois=12 then
      NbrJourMois := (CalcNbrJour(1,1,Annee+1)-CalcNbrJour(1,Mois,Annee))
    else
      NbrJourMois := (CalcNbrJour(1,Mois+1,Annee)-CalcNbrJour(1,Mois,Annee));
    { Calcul du premier jour de la semaine du mois }
    JourSem := CalcNbrJour(1,Mois,Annee) mod 7;
    { Affiche le calendrier du mois en cours }
    px := 32;
    py := 50;
    SetLineStyle(SolidLn,0,1);
    For i:=1 to NbrJourMois do
    Begin
      JourEnCours := CalcNbrJour(i,Mois,Annee);
      If (JourEnCours>Aujourdhui) then Co := Black
        else if (JourEnCours<Aujourdhui) then Co:=DarkGray
          else co := Green;
      TabXY[i].x := px;
      TabXY[i].y := py;
      AffichJour(i,Mois,Annee,Co);
      Line(px+48,py+5,px+272,py+5);
      If JourSem=0 Then
      Begin
        SetColor(Blue);
        SetLineStyle(SolidLn,0,3);
        Line(px,py+15,px+272,py+15);
        Inc(py,30);
        SetlineStyle(SolidLn,0,1);
        SetColor(Blue);
      end
      else
        Inc(Py,15);
      JourSem := (JourSem + 1) mod 7;
      If i=16 then begin py:=50; px:=336; end;
    end;
    ChangeMois := False;
    if (Jour>NbrJourMois) then Jour := NbrJourMois;
    AffichJour(jour,mois,annee,Red);
    Repeat
      JourEnCours := CalcNbrJour(Jour,Mois,Annee);
      If (JourEnCours>Aujourdhui) then Co := Black
        else if (JourEnCours<Aujourdhui) then Co:=DarkGray
          else co := Green;
      Ch := ReadKey;
      case ch of
        #10 : Begin                  { Ctrl-Enter }
                RAZ := True;
                ChangeMois := True;
              end;
        #13 : Begin
                ChangeFich := ChangeRem(Jour,Mois, Annee) or ChangeFich;
              end;
        #27 : Begin                  { ESC }
                Sortie := True;
                RAZ := True;
                ChangeMois := True;
              end;
        #0  : Begin
                Ch := ReadKey;
                case Ch of
                  'G' : Begin        { Home }
                          AffichJour(Jour,Mois,Annee,Co);
                          Jour := 1;
                          AffichJour(Jour,Mois,Annee,Red);
                        end;
                  'O' : Begin        { End }
                          AffichJour(Jour,Mois,Annee,Co);
                          Jour := NbrJourMois;
                          AffichJour(Jour,Mois,Annee,Red);
                        end;
                  'H' : Begin        { Haut }
                          AffichJour(Jour,Mois,Annee,Co);
                          Dec(Jour);
                          If (Jour<1) then
                          Begin
                            Jour:=31;
                            Dec(Mois);
                            If (Mois<1) then
                            Begin
                              If ChangeFich Then EcritFich(Annee);
                              Dec(Annee); Mois:=12; InitNouvAnnee(Annee);
                              ChangeFich := false;
                            end;
                            ChangeMois := True;
                          end
                          else
                            AffichJour(Jour,Mois,Annee,Red);
                        end;
                  'P' : Begin        { Bas }
                          AffichJour(Jour,Mois,Annee,Co);
                          Inc(Jour);
                          If (Jour>NbrJourMois) then
                          Begin
                            Jour:=1;
                            Inc(Mois);
                            If (Mois>12) then
                            Begin
                              If ChangeFich Then EcritFich(Annee);
                              Inc(Annee); Mois:=1; InitNouvAnnee(Annee);
                              ChangeFich := False;
                            end;
                            ChangeMois := True;
                          end
                          else
                            AffichJour(Jour,Mois,Annee,Red);
                        end;
                  'K' : If (Jour>16) then { Gauche }
                        Begin
                          AffichJour(Jour,Mois,Annee,Co);
                          Jour := Jour - 16;
                          AffichJour(Jour,Mois,Annee,Red);
                        end
                        else Bip;
                  'M' : If (Jour<17) and (Jour+16<=NbrJourMois) then { Droite }
                        Begin
                          AffichJour(Jour,Mois,Annee,Co);
                          Jour := Jour + 16;
                          AffichJour(Jour,Mois,Annee,Red);
                        end
                        else Bip;
                  'I' : Begin        { PgUp }
                          Dec(Mois);
                          If (Mois<1) then
                          Begin
                            If ChangeFich then EcritFich(Annee);
                            Dec(Annee); Mois:=12; InitNouvAnnee(Annee);
                            ChangeFich := false;
                          end;
                          ChangeMois := True;
                        end;
                  'Q' : Begin        { PgDw }
                          Inc(Mois);
                          If (Mois>12) then
                          Begin
                            If ChangeFich then EcritFich(Annee);
                            Inc(Annee); Mois:=1; InitNouvAnnee(Annee);
                            ChangeFich := False;
                          end;
                          ChangeMois := True;
                        end;
                  #117 : Begin       { Ctrl-Fin }
                          Mois := 12;
                          ChangeMois:=True;
                         end;
                  #119 : Begin       { Ctrl-Home }
                           Mois := 1;
                           ChangeMois:=True;
                         end;
                  #118 : Begin       { Ctrl-PdDw }
                           If ChangeFich then EcritFich(Annee);
                           Inc(Annee);
                           InitNouvAnnee(Annee);
                           ChangeFich := False;
                           ChangeMois := True;
                         end;
                  #132 : Begin       { Ctrl-PgUp }
                           If ChangeFich then EcritFich(Annee);
                           Dec(Annee);
                           InitNouvAnnee(Annee);
                           ChangeFich := False;
                           ChangeMois := True;
                         end;
                  else Bip;
                end;
              end;
        else Bip;
 
      end;
    Until ChangeMois;
  Until (RAZ);
  If ChangeFich then EcritFich(Annee);
  ChangeFich := False;
  Until (Sortie);
end;
 
(*
 *  Annonce un evenement pour aujourd'hui ou pour demain
 *)
 
Function Annonce(i : Word; St : String) : Byte;
 
Begin
  If EvtDuJour[i]<>'' then
  Begin
    Writeln(St + ' : ' + EvtDuJour[i]);
    Annonce := 1;
  end else Annonce := 0;
end;
 
 
(*
 *  Calendrier automatique
 *)
 
Procedure AutoCald;
 
Var JDS,Jour, Mois, Annee : Word;
    Ch : Char;
 
Begin
  GetDate(Annee,Mois,Jour,JDS);
  InitNouvAnnee(Annee);
  If (Annonce(NbJour(Jour,Mois,Annee)+1,'Demain') +
      Annonce(NbJour(Jour,Mois,Annee),'Aujourd''hui') > 0) then
  Begin
    DingDong;
    WriteLn;
    Write('Taper sur une touche pour continuer...');
    Repeat until KeyPressed;
    While KeyPressed do Ch := ReadKey;
    WriteLn;
  end
  else
    WriteLn('Pas d''événement important pour aujourd''hui ou pour demain.');
end;
 
(*
 *  Programme principal
 *)
 
Begin
  If (ParamCount=1) and ((ParamStr(1) = '/a') or (ParamStr(1) = '/A'))
  then AutoCald
  else
  Begin
    InitGraph;
    AffCalendrier;
    CloseGraph;
  end;
end. 

© COPYRIGHT 1993 PAR F.HARDY