Page 1 sur 2

Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : jeu. 22/avr./2021 9:43
par jak64
Bonjour,
64 lignes de code qui permettent de savoir si une date donnée tombe un jour férié (y compris les fêtes mobiles comme le lundi de Pâques, le Lundi de Pentecôte ou le jeudi de l'Ascension).
Pour des besoins professionnels, il y a plus de 20 ans, (j'en ai 66), je devais calculer la disponibilité de Services Bancaires et j'avais besoin de connaître les jours fériés (y compris mobiles). Il y avait bien sûr la possibilité de mettre ces dates en "dur" dans des paramètres mais je souhaitais une solution automatique ce qui éviterait les erreurs si on oubliait de mettre à jour ces dates manuellement.
En fouillant sur Internet (c'était presque le début), j'avais trouvé une formule mise au point par des moines, de ce que je me souviens. J'avais adapté la formule à VBA (que j'utilisais à l'époque).
Ci-dessous, voici le code en Purebasic. Bien sûr, ce code peut-être adapté pour qu'il corresponde à votre besoin (par exemple, boucler sur une année pour rechercher tous les jours fériés).
Cordialement,
Jacques Joly

Code : Tout sélectionner

EnableExplicit
Global Dim t_jours.s(16)
Global j.b

Procedure.b jour_ferie(jour.w,mois.w,annee.w)
  Protected A.w,T.i,LP.i,LD.i,retour.b
  If Date(annee,mois,jour,0,0,0)=-1
    MessageRequester("Erreur","La date passée en paramètre n'est pas une date valide")
    ProcedureReturn -1
  EndIf
  ;=---------- La date passée en paramètre est valide
  A=annee
  LD=Int(Date(annee,mois,jour,0,0,0))/86400+25569
  ;=---------- Formule mise au point par des moines
  T=Mod(255-11*Mod(A,19)-21,30)+21
  LP=Date(A,3,2,0,0,0)/86400+25569+T+Bool(T>48)+6-Mod((A+Int(A/4)+T+Bool(T>48)+1),7)
  ;=---------- Interprétation du résultat
  If LD=LP                    : retour=7  ; Lundi de Pâques
  ElseIf LD=LP+38             : retour=8  ; Jeudi de l'Ascension
  ElseIf LD=LP+49             : retour=9  ; Lundi de Pentecôte
  ElseIf jour=1 And mois=1    : retour=10 ; Jour de l'an
  ElseIf jour=1 And mois=5    : retour=11 ; 1er mai
  ElseIf jour=8 And mois=5    : retour=12 ; 8 mai
  ElseIf jour=14 And mois=7   : retour=13 ; 14 juillet
  ElseIf jour=15 And mois=8   : retour=14 ; 15 août
  ElseIf jour=1 And mois=11   : retour=15 ; 1er novembre
  ElseIf jour=11 And mois=11  : retour=16 ; 11 novembre
  ElseIf jour=25 And mois=12  : retour=17 ; Noël
  Else
    retour=DayOfWeek(Date(annee,mois,jour,0,0,0)) ; 0=dimanche, lundi=1, mardi=2.....
  EndIf
  ProcedureReturn retour
EndProcedure

;=---------- Charger les jours dans le tableau
Restore jours_feries
For j=0 To 16
  Read.s t_jours(j)
Next j

;=---------- Test fonction
Debug t_jours(jour_ferie(18,4,2022)) ; jour,mois,année

DataSection
  jours_feries:
  Data.s "Dimanche"
  Data.s "Lundi"
  Data.s "Mardi"
  Data.s "Mercredi"
  Data.s "Jeudi"
  Data.s "Vendredi"
  Data.s "Samedi"
  Data.s "Lundi de Pâques"
  Data.s "Jeudi de l'Ascension"
  Data.s "Lundi de Pentecôte"
  Data.s "Jour de l'an"
  Data.s "1er mai"
  Data.s "8 mai"
  Data.s "14 juillet"
  Data.s "15 août"
  Data.s "1er novembre"
  Data.s "11 novembre"
  Data.s "Noël"
EndDataSection

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : jeu. 22/avr./2021 10:26
par jak64
Plantage quand la date passée en paramètre n'est pas valide :( , j'ai corrigé dans le code ci-dessous.

Code : Tout sélectionner

EnableExplicit
Global Dim t_jours.s(18)
Global j.b

Procedure.b jour_ferie(jour.w,mois.w,annee.w)
  Protected A.w,T.i,LP.i,LD.i,retour.b
  If Date(annee,mois,jour,0,0,0)=-1
    retour=18
  Else
    ;=---------- La date passée en paramètre est valide
    A=annee
    LD=Int(Date(annee,mois,jour,0,0,0))/86400+25569
    ;=---------- Formule mise au point par des moines
    T=Mod(255-11*Mod(A,19)-21,30)+21
    LP=Date(A,3,2,0,0,0)/86400+25569+T+Bool(T>48)+6-Mod((A+Int(A/4)+T+Bool(T>48)+1),7)
    ;=---------- Interprétation du résultat
    If LD=LP                    : retour=7  ; Lundi de Pâques
    ElseIf LD=LP+38             : retour=8  ; Jeudi de l'Ascension
    ElseIf LD=LP+49             : retour=9  ; Lundi de Pentecôte
    ElseIf jour=1 And mois=1    : retour=10 ; Jour de l'an
    ElseIf jour=1 And mois=5    : retour=11 ; 1er mai
    ElseIf jour=8 And mois=5    : retour=12 ; 8 mai
    ElseIf jour=14 And mois=7   : retour=13 ; 14 juillet
    ElseIf jour=15 And mois=8   : retour=14 ; 15 août
    ElseIf jour=1 And mois=11   : retour=15 ; 1er novembre
    ElseIf jour=11 And mois=11  : retour=16 ; 11 novembre
    ElseIf jour=25 And mois=12  : retour=17 ; Noël
    Else
      retour=DayOfWeek(Date(annee,mois,jour,0,0,0)) ; 0=dimanche, lundi=1, mardi=2.....
    EndIf
  EndIf 
  ProcedureReturn retour
EndProcedure

;=---------- Charger les jours dans le tableau
Restore jours_feries
For j=0 To 18
  Read.s t_jours(j)
Next j

;=---------- Test fonction
Debug t_jours(jour_ferie(6,6,2022)) ; jour,mois,année

DataSection
  jours_feries:
  Data.s "Dimanche"
  Data.s "Lundi"
  Data.s "Mardi"
  Data.s "Mercredi"
  Data.s "Jeudi"
  Data.s "Vendredi"
  Data.s "Samedi"
  Data.s "Lundi de Pâques"
  Data.s "Jeudi de l'Ascension"
  Data.s "Lundi de Pentecôte"
  Data.s "Jour de l'an"
  Data.s "1er mai"
  Data.s "8 mai"
  Data.s "14 juillet"
  Data.s "15 août"
  Data.s "1er novembre"
  Data.s "11 novembre"
  Data.s "Noël"
  Data.s "La date passée en paramètre n'est pas une date valide"
EndDataSection

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : jeu. 22/avr./2021 10:54
par Marc56
Intéressant ce code. Léger: j'aime, surtout à notre époque où la normalité est d'écrire le plus de ligne possible :)
Cela me rappelle l'époque il y a aussi presque une vingtaine d'années où j'avais dû écrire divers codes pour déclencher des batchs le premier et dernier jour ouvrés de chaque mois, car on risquait d'oublier ou de se tromper en programmant le contrab unix.
Merci, je mets ça de côté. :wink:

PS. Tu peux éditer ton code initial avec l'icône crayon en haut à droite.

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : jeu. 22/avr./2021 11:12
par jak64
Merci Marc pour ce retour.
Pour info, j'ai écrit, depuis 1 an que je connais Purebasic, 7 ou 8 programmes, dans le section Jeux (petits jeux et aussi recherche dichotomique pour composer tous les mots possibles avec de 2 à 10 lettres). Vous pouvez les trouver en recherchant sur mon pseudo jak64 (Je ne sais pas, par contre, si c'est possible de rechercher par pseudo).
Cordialement.

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : jeu. 22/avr./2021 13:50
par Micoute
Bonjour jak64,

ton programme est génial, mais tu aurais dû mettre:

;=---------- Test fonction
CompilerIf #PB_Compiler_IsMainFile
Debug t_jours(jour_ferie(6,6,2022)) ; jour,mois,année
CompilerEndIf

avec cette méthode, on peut inclure ton programme dans un autre pour vérifier les jours fériés.

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : jeu. 22/avr./2021 18:54
par jak64
Bonjour Micoute,
Merci de votre retour.
Je n'utilise Purebasic que depuis 1 an et je ne connais pas ces instructions. Comme j'ai mis le code source, je pense que les personnes intéressées pourront utiliser vos conseils.
Cordialement,
Jacques Joly

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 9:27
par MLD
Bonjour jak64
Il y a quelques temps j'ai fait ceci.
Il semble qu'il y a des divergences avec ton programme de date (Voir pâques 2030)

Code : Tout sélectionner

;Calcul de la date de paque pour calendrier grégorien
Procedure calulftrelig(jr,mr,y)
datref$ = FormatDate("%dd%mm%yyyy",Date(y,mr,jr,0,0,0)) 
;dimanche de paque
c.w = y / 100 
n.w =  (y % 19) 
k.w = (c - 17) / 25 
b.w = c /4 
e.w = (c - k) / 3 
f.w = c - b - e + (19 * n) + 15 
h.w =  (f % 30) 
p.w = h / 28 
q.w = 29 / (h + 1)
r.w = (21 - n) / 11 
i.w = h - (p * (1 - (p * q * r)))
s.w = y / 4 
t.w = c / 4 
u.w = y + s + i + 2 - c + t 
j.w =  (u % 7) 
w.w = (i - j + 40) / 44  
m.w = 3 + w  
x.w = m / 4 
d.w = i - j + 28 - (31 * x)
 Dimanchepaque$ = FormatDate("%dd%mm%yyyy",Date(y,m,d,0,0,0))  
 lundipaque$ = FormatDate("%dd%mm%yyyy",AddDate(Date(y,m,d,0,0,0),#PB_Date_Day,1))
 jeudiasc$ = FormatDate("%dd%mm%yyyy",AddDate(Date(y,m,d,0,0,0),#PB_Date_Day,39))
 dimanchepent$ =  FormatDate("%dd%mm%yyyy",AddDate(Date(y,m,d,0,0,0),#PB_Date_Day,49))
 lundipent$ = FormatDate("%dd%mm%yyyy",AddDate(Date(y,m,d,0,0,0),#PB_Date_Day,50)) 
 indftm.b = 0
 If datref$ = Dimanchepaque$
  indftm.b = 1
 EndIf 
 If datref$ = lundipaque$
  indftm.b = 1
 EndIf 
 If datref$ = jeudiasc$
  indftm.b = 1
 EndIf
 If datref$ = dimanchepent$
  indftm.b = 1
 EndIf  
 If datref$ = lundipent$
  indftm.b = 1
 EndIf
   
 Debug " Date de ref"  + "   " + datref$
 Debug "Dimanche de paque" +"  " +Dimanchepaque$
 Debug "Lundi de paque" +"  " +lundipaque$
 Debug "Jeudi de l'ascention" +"  " + jeudiasc$
 Debug "Dimanche de pentecote" +"  " + dimanchepent$
 Debug "Lundi de pentecote" +"  " + lundipent$
 
ProcedureReturn indftm.b
EndProcedure
 Debug  calulftrelig(01,01,2030)

Michel

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 11:47
par jak64
Bonjour MLD,
Je viens de vérifier, Le dimanche de Pâques 2030 est le 21 avril 2030, donc le lundi de Pâques 2030 est le lundi 22 avril 2030. C'est bien ce que dit mon programme si on met "Debug t_jours(jour_ferie(22,4,2030))".

Cordialement,

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 15:00
par MLD
J'ai indiquer dans t_jours(jour_ferie(21,4,2030))" jour de pâques le débug répond simplement dimanche.
Comme j'ai la tête en l'air, le lundi je me pointe au bureau, j'utilise ton logiciel, et là 8O 8O Nom d'un Belzébute en bois , je n'est plus qu'a renter chez moi. :mrgreen:
Ou alors je n'est rien compris. :roll: :roll:
Pourquoi tu n'indique pas que le dimanche est le jour de pâque, et que le lendemain est jour férié. :?: :?:
PS: si je condense un peu mon code il doit pouvoir tenir en moins de 50 lignes :lol:

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 15:17
par jak64
Bonjour MLD,
Pour les distraits :lol: voici le code qui prend en compte le dimanche de Pâques et le dimanche de Pentecôte.

Code : Tout sélectionner

EnableExplicit
Global Dim t_jours.s(21)
Global j.b

Procedure.b jour_ferie(jour.w,mois.w,annee.w)
  Protected A.w,T.i,LP.i,LD.i,retour.b
  If Date(annee,mois,jour,0,0,0)=-1
    retour=21
  Else
    ;=---------- La date passée en paramètre est valide
    A=annee
    LD=Int(Date(annee,mois,jour,0,0,0))/86400+25569
    ;=---------- Formule mise au point par des moines
    T=Mod(255-11*Mod(A,19)-21,30)+21
    LP=Date(A,3,2,0,0,0)/86400+25569+T+Bool(T>48)+6-Mod((A+Int(A/4)+T+Bool(T>48)+1),7)
    ;=---------- Interprétation du résultat
    If LD=LP-1                  : retour=7  ; Dimanche de Pâques
    ElseIf LD=LP                : retour=8  ; Lundi de Pâques
    ElseIf LD=LP+38             : retour=9  ; Jeudi de l'Ascension
    ElseIf LD=LP+48             : retour=10 ; Dimanche de Pentecôte
    ElseIf LD=LP+49             : retour=11 ; Lundi de Pentecôte
    ElseIf jour=1 And mois=1    : retour=12 ; Jour de l'an
    ElseIf jour=1 And mois=5    : retour=13 ; 1er mai
    ElseIf jour=8 And mois=5    : retour=14 ; 8 mai
    ElseIf jour=14 And mois=7   : retour=15 ; 14 juillet
    ElseIf jour=15 And mois=8   : retour=16 ; 15 août
    ElseIf jour=1 And mois=11   : retour=17 ; 1er novembre
    ElseIf jour=11 And mois=11  : retour=18 ; 11 novembre
    ElseIf jour=25 And mois=12  : retour=19 ; Noël
    Else
      retour=DayOfWeek(Date(annee,mois,jour,0,0,0)) ; 0=dimanche, lundi=1, mardi=2.....
    EndIf
  EndIf 
  ProcedureReturn retour
EndProcedure

;=---------- Charger les jours dans le tableau
Restore jours_feries
For j=0 To 21
  Read.s t_jours(j)
Next j

;=---------- Test fonction
Debug t_jours(jour_ferie(21,4,2030)) ; jour,mois,année

DataSection
  jours_feries:
  Data.s "Dimanche"
  Data.s "Lundi"
  Data.s "Mardi"
  Data.s "Mercredi"
  Data.s "Jeudi"
  Data.s "Vendredi"
  Data.s "Samedi"
  Data.s "Dimanche de Pâques"
  Data.s "Lundi de Pâques"
  Data.s "Jeudi de l'Ascension"
  Data.s "Dimanche de Pentecôte"  
  Data.s "Lundi de Pentecôte"
  Data.s "Jour de l'an"
  Data.s "1er mai"
  Data.s "8 mai"
  Data.s "14 juillet"
  Data.s "15 août"
  Data.s "1er novembre"
  Data.s "11 novembre"
  Data.s "Noël"
  Data.s "Dimanche de Pâques"
  Data.s "La date passée en paramètre n'est pas une date valide"
EndDataSection

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 15:21
par jak64
Comme je le disais dans mon propos dans le premier post, cette routine était utilisée pour calculer la disponibilité de Services Bancaires et ce qui importait c'était de ne pas comptabiliser les coupures si le jour était férié, et le dimanche, les agences n'étaient pas ouvertes, c'est pourquoi il ne m'importait pas que ce soit le dimanche de Pâques ou un dimanche "normal"...
Cordialement,

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 15:23
par jak64
De plus, je ne fais pas la course à qui fera en moins de lignes, j'ai passé l'âge (J'ai 66 ans) :wink:

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 17:00
par MLD
Bonsoir Jak64
De plus, je ne fais pas la course à qui fera en moins de lignes, j'ai passé l'âge (J'ai 66 ans)
OK mais tu y fait souvent référence. Ne le prend pas mal c'est une taquinerie :lol:
Pour mon âge, je te laisse le choix entre 10 et 80 ans. :?: :lol: :lol: J'ai commencé la programmation sur un Amstrad
Donc avec très peu de mémoire, ce qui ma formé a faire des codes le plus court possible, ce qui est souvent un gage de fiabilité du code.
Trop de code pour une petite fonction, il y a un loup. Ce n'est plus vraiment ce que l'on apprend maintenant dans les écoles d'informatique. :roll: :?

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 17:19
par jak64
Amstrad CPC 6128 mais c'est très récent :wink:

Moi j'ai commencé en Cobol (en 1975), en écrivant les lignes de code au crayon de papier sur des feuilles 80 colonnes qui étaient ensuite données au Service des Perforatrices (il n'y avait que des femmes, à cette époque qui faisaient ce travail) qui, avec leurs machines spéciales, tapaient notre code qui ressortait sur des cartes perforées (Il ligne de code = 1 carte perforée). Valait mieux pas faire tomber son paquet de cartes (on numérotait chaque instruction, sur nos feuilles, au cas où).
Ensuite, On donnait nos cartes au Service Exploitation. Le paquet de cartes étaient lues dans le lecteur de cartes pour faire la compilation et on récupérait un listing avec les erreurs éventuelles. On n'avait droit qu'à une compilation par jour, valait mieux être précis, en Cobol, un . (point) manquant et c'était une erreur.

Et j'ai eu un Apple 2, un VideoGenie, un TRS80, un Commodore, un TI99, un CPC, etc... Et j'ai toujours aimé programmer, même aujourd'hui où je suis à la retraite, mais par contre, pas en 3D :( pour l'instant...

Bien cordialement,

Re: Fonction jours fériés (y compris fêtes mobiles, Pâques, etc.)

Publié : dim. 25/avr./2021 23:10
par jak64
Bonjour,
J'ai modifié le code pour en faire une fonction indépendante qui peut être intégrée dans un programme.

Code : Tout sélectionner

Procedure.s jour_ferie(jour.w,mois.w,annee.w)
  Protected A.w,T.i,LP.i,LD.i,retour.b,Dim t_jours.s(21),j.b
  ;=---------- Charger les jours dans le tableau
  Restore jours_feries
  For j=0 To 21
    Read.s t_jours(j)
  Next j
  If Date(annee,mois,jour,0,0,0)=-1
    retour=21 ; La date passée en paramètre n'est pas valide
  Else
    ;=---------- La date passée en paramètre est valide
    A=annee
    LD=Int(Date(annee,mois,jour,0,0,0))/86400+25569
    ;=---------- Formule mise au point par des moines
    T=Mod(255-11*Mod(A,19)-21,30)+21
    LP=Date(A,3,2,0,0,0)/86400+25569+T+Bool(T>48)+6-Mod((A+Int(A/4)+T+Bool(T>48)+1),7)
    ;=---------- Interprétation du résultat
    If LD=LP-1                  : retour=7  ; Dimanche de Pâques
    ElseIf LD=LP                : retour=8  ; Lundi de Pâques
    ElseIf LD=LP+38             : retour=9  ; Jeudi de l'Ascension
    ElseIf LD=LP+48             : retour=10 ; Dimanche de Pentecôte
    ElseIf LD=LP+49             : retour=11 ; Lundi de Pentecôte
    ElseIf jour=1 And mois=1    : retour=12 ; Jour de l'an
    ElseIf jour=1 And mois=5    : retour=13 ; 1er mai
    ElseIf jour=8 And mois=5    : retour=14 ; 8 mai
    ElseIf jour=14 And mois=7   : retour=15 ; 14 juillet
    ElseIf jour=15 And mois=8   : retour=16 ; 15 août
    ElseIf jour=1 And mois=11   : retour=17 ; 1er novembre
    ElseIf jour=11 And mois=11  : retour=18 ; 11 novembre
    ElseIf jour=25 And mois=12  : retour=19 ; Noël
    Else
      retour=DayOfWeek(Date(annee,mois,jour,0,0,0)) ; 0=dimanche, lundi=1, mardi=2.....
    EndIf
  EndIf 
  ProcedureReturn t_jours(retour)
  DataSection
    jours_feries:
    Data.s "Dimanche"
    Data.s "Lundi"
    Data.s "Mardi"
    Data.s "Mercredi"
    Data.s "Jeudi"
    Data.s "Vendredi"
    Data.s "Samedi"
    Data.s "Dimanche de Pâques"
    Data.s "Lundi de Pâques"
    Data.s "Jeudi de l'Ascension"
    Data.s "Dimanche de Pentecôte"  
    Data.s "Lundi de Pentecôte"
    Data.s "Jour de l'an"
    Data.s "1er mai"
    Data.s "8 mai"
    Data.s "14 juillet"
    Data.s "15 août"
    Data.s "1er novembre"
    Data.s "11 novembre"
    Data.s "Noël"
    Data.s "Dimanche de Pâques"
    Data.s "La date passée en paramètre n'est pas une date valide"
  EndDataSection
EndProcedure


;=---------- Test fonction
Debug jour_ferie(21,4,2030) ; jour,mois,année