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

Programmation d'applications complexes
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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
Marc56
Messages : 2148
Inscription : sam. 08/févr./2014 15:19

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

Message 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.
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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.
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

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

Message 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.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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
Avatar de l’utilisateur
MLD
Messages : 1105
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

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

Message 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
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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,
Avatar de l’utilisateur
MLD
Messages : 1105
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

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

Message 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:
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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,
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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:
Avatar de l’utilisateur
MLD
Messages : 1105
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

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

Message 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: :?
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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,
Avatar de l’utilisateur
jak64
Messages : 85
Inscription : dim. 03/mai/2020 23:16

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

Message 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

Répondre