Outils pour utilisateurs

Outils du site


date_de_paques

Calcul de la date de Pâques et des jours fériés (France)

(refonte complète de la page le 13/10/2009)

Calcul de la date de Pâques

La date de Pâques est assez complexe à calculer et encore plus à comprendre. Mais elle est importante pour calculer les jours fériés qui y sont liés.

Les différentes méthodes sont ici: http://users.chariot.net.au/~gmarts/eastalg.htm

J'ai choisi de programmer la méthode Hodges: http://users.chariot.net.au/~gmarts/eastalg.htm#EasterHodges

J'ai vérifié ensuite avec toutes les dates ici: http://www.dioceserimouski.com/ch/paquesdates.html

Ce calcul n'est valable que pour le calendrier grégorien avec des dates comprises entre 1583 et 4100 (ce qui devrait suffire pour les jours fériés :-D).

Codage:

def datepaques(an):
    """Calcule la date de Pâques d'une année donnée an (=nombre entier)"""
    a=an//100
    b=an%100
    c=(3*(a+25))//4
    d=(3*(a+25))%4
    e=(8*(a+11))//25
    f=(5*a+b)%19
    g=(19*f+c-e)%30
    h=(f+11*g)//319
    j=(60*(5-d)+b)//4
    k=(60*(5-d)+b)%4
    m=(2*j-k-g+h)%7
    n=(g-h+m+114)//31
    p=(g-h+m+114)%31
    jour=p+1
    mois=n
    return [jour, mois, an]
 
# Exemple d'utilisation:
print paques(2008)  #  affiche [23, 3, 2008]

L'année voulue est toujours donnée en année complète (type 2008) et pas en raccourcis (type 08).

Il ensuite facile de calculer les dates des jours fériés France avec une fonction qui ajoute et retranche les dates:

Jeudi de l'ascension = Pâques +39

Lundi de Pentecôte = Pâques + 50

Etc…

Présentation des fonctions nécessaires pour le calcul des jours fériés

Conversion date-chaîne date-liste

Les calculs internes avec les dates se font en date-liste d=[13,10,2009] pour éviter les conversions inutiles. Mais on a besoin de fonction de conversion pour:

  • convertir des dates-chaînes en entrée, en dates-listes pour les calculs
  • convertir des dates-listes issues des calculs, en dates-chaînes pour affichage ou stockage.

1er cas: J'ai une date sous forme de chaîne de caractères c=“13/10/2009”, je veux la transformer en date liste: d=[13,10,2009]:

def dateliste(c, sep='/'):
    """Transforme une date chaîne 'j/m/a' en une date liste [j,m,a]"""
    j, m, a = c.split(sep)
    return [int(j), int(m), int(a)]

Et le contraire: j'ai une date-liste d=[13,10,2009] et je veux la transformer en date-chaîne c=“13/10/2009”

def datechaine(d, sep='/'):
    """Transforme une date liste=[j,m,a] en une date chaîne 'jj/mm/aaaa'"""
    return ("%02d" + sep + "%02d" + sep + "%0004d") % (d[0], d[1], d[2])

Dans les 2 cas, on peut préciser le séparateur qui est '/' par défaut. Avec cela, on peut convertir “13/10/2009” ou “13-10-2009” ou “13:10:2009” ou avec n'importe quel autre séparateur.

Additionner ou soustraire n jours à une date donnée

Les 2 codes suivants permettent d'additionner ou de soustraire un certain nombre de jours à une date donnée, et de trouver la nouvelle date.

Ces codes ne sont pas très subtils (calcul jour par jour) mais ils sont faciles à comprendre et sont suffisamment rapides ici.

Fonction pour additionner n jours (n>=0) à la date d=[j,m,a]:

def jourplus(d, n=1):
    """Donne la date du nième jour suivant d=[j, m, a] (n>=0)"""
    j, m, a = d
    fm = [0,31,28,31,30,31,30,31,31,30,31,30,31]
    if (a%4==0 and a%100!=0) or a%400==0:  # bissextile?
        fm[2] = 29
    for i in xrange(0,n):
        j += 1
        if j > fm[m]:
            j = 1
            m += 1
            if m>12:
                m = 1
                a += 1
    return [j,m,a]

Fonction pour soustraire n jours (n<=0) à la date d=[j,m,a]:

def jourmoins(d, n=-1):
    """Donne la date du nième jour précédent d=[j, m, a] (n<=0)"""
    j, m, a = d
    fm = [0,31,28,31,30,31,30,31,31,30,31,30,31]
    if (a%4==0 and a%100!=0) or a%400==0:  # bissextile?
        fm[2] = 29
    for i in xrange(0,abs(n)):
        j -= 1
        if j < 1:
            m -= 1
            if m<1:
                m = 12
                a -= 1
            j = fm[m]
    return [j,m,a]

Calculer le jour de semaine d'une date donnée

Le but est de dire si une date donnée d=[j,m,a] est un lundi, mardi, …

J'ai choisi l'algorithme de Maurice Kraitchik (1882–1957), et je l'ai trouvé ici: http://cosmos2000.chez.com/Vendredi13/KraitchikMethode.html.

La 1ère fonction donne le numéro du jour de semaine (1 pour lundi, 2 pour mardi, …, 7 pour dimanche).

La seconde fonction renvoie le jour de semaine en texte. Ex: “Mercredi” pour n=3.

def numjoursem(d):
    """Donne le numéro du jour de la semaine d'une date d=[j,m,a]
       lundi=1, mardi=2, ..., dimanche=7
       Algorithme de Maurice Kraitchik (1882–1957)"""
    j, m, a = d
    if m<3:
        m += 12
        a -= 1
    n = (j +2*m + (3*(m+1))//5 +a + a//4 - a//100 + a//400 +2) % 7
    return [6, 7, 1, 2, 3, 4, 5][n]
 
def joursem(d):
    """Donne le jour de semaine en texte à partir de son numéro
       lundi=1, mardi=2, ..., dimanche=7"""
    return ["", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi",
             "dimanche"][numjoursem(d)]

Voilà. On a toutes les fonctions nécessaires pour calculer les jours fériés!

Calcul des jours fériés France d'une année quelconque

Ma référence pour les jours fériés France: http://fr.wikipedia.org/wiki/F%C3%AAtes_et_jours_f%C3%A9ri%C3%A9s_en_France

Les fonctions ci-dessous renvoient la liste des jours fériés France à partir d'une année quelconque.

Ces fonctions utilisent uniquement les fonctions décrites ci-dessus sur cette page

Le 2ème paramètre numérique est optionnel:

  • sd=0 (=defaut): tous les jours fériés.
  • sd=1: idem sans les samedis-dimanches.
  • sd=2: les jours fériés + les 2 jours fériés supplémentaires d'Alsace-Moselle.
  • sd=3: idem sd=2 sans les samedis-dimanches“”“

Vous pouvez adapter les jours fériés selon votre situation, région, pays, besoins et évolution de la législation.

Pour ce qui concerne le lundi de la Pentecôte, vous faites comme vous avez compris… :-D

J'ai découpé en 2 fonctions:

  • la 1ère renvoie la liste des dates sous forme de date-liste d=[j,m,a],
  • la seconde exploite cette liste pour les présenter sous forme de date-chaine c=“jj/mm/aaaa”.

L'avantage de ce découpage en 2 fonctions est qu'on peut utiliser la 1ère fonction pour d'autres calculs.

Pour la seconde fonction, on peut préciser le séparateur à utiliser pour stocker la date sous forme de date-chaine ('/' par défaut)

Première fonction

def joursferiesliste(an, sd=0):
    """Liste des jours fériés France en date-liste de l'année an (nb entier). 
         sd=0 (=defaut): tous les jours fériés. 
         sd=1: idem sans les sammedis-dimanches. 
         sd=2: tous + les 2 jours fériés supplémentaires d'Alsace-Moselle. 
         sd=3: idem sd=2 sans les samedis-dimanches"""
    F = []  # =liste des dates des jours feries en date-liste d=[j,m,a]
    L = []  # =liste des libelles du jour ferie
    dp = datepaques(an)
 
    # Jour de l'an
    d = [1,1,an]
    nj = numjoursem(d)
    if (sd==0) or (sd==1 and nj<6) or (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Jour de l'an")
 
    # Vendredi saint (pour l'Alsace-Moselle)
    d = jourmoins(dp, -2)
    if sd>=2:
        F.append(d)
        L.append(u"Vendredi saint")
 
    # Dimanche de Paques
    d = dp
    if (sd==0) or (sd==2):
        F.append(d)
        L.append(u"Dimanche de Pâques")
 
    # Lundi de Paques
    d = jourplus(dp, +1)
    F.append(d)
    L.append(u"Lundi de Pâques")
 
    # Fête du travail
    d = [1,5,an]
    nj = numjoursem(d)
    if (sd==0) or (sd==1 and nj<6) or (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Fête du travail")
 
    # Victoire des allies 1945
    d = [8,5,an]
    nj = numjoursem(d)
    if (sd==0) or (sd==1 and nj<6) or (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Victoire des alliés 1945")
 
    # Jeudi de l'Ascension
    d = jourplus(dp, +39)
    F.append(d)
    L.append(u"Jeudi de l'Ascension")
 
    # Dimanche de Pentecote
    d = jourplus(dp, +49)
    if (sd==0) or (sd==2):
        F.append(d)
        L.append(u"Dimanche de Pentecôte")
 
    # Lundi de Pentecote
    d = jourplus(d, +1)
    F.append(d)
    L.append(u"Lundi de Pentecôte")
 
    # Fete Nationale
    d = [14,7,an]
    nj = numjoursem(d)
    if (sd==0) or (sd==1 and nj<6) or (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Fête Nationale")
 
    # Assomption
    d = [15,8,an]
    nj = numjoursem(d)
    if (sd==0) or (sd==1 and nj<6) or (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Assomption")
 
    # Toussaint
    d = [1,11,an]
    nj = numjoursem(d)
    if (sd==0) or (sd==1 and nj<6) or (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Toussaint")
 
    # Armistice 1918
    d = [11,11,an]
    nj = numjoursem(d)
    if (sd==0) or (sd==1 and nj<6) or (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Armistice 1918")
 
    # Jour de Noel
    d = [25,12,an]
    nj = numjoursem(d)
    if (sd==0) or (sd==1 and nj<6) or (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Jour de Noël")
 
    # Saint Etienne (pour l'Alsace-Moselle)
    d = [26,12,an]
    nj = numjoursem(d)
    if (sd==2) or (sd==3 and nj<6):
        F.append(d)
        L.append(u"Saint Etienne")
 
    return F, L

Seconde fonction:

def joursferies(an, sd=0, sep='/'):
    """Liste des jours fériés France en date-chaine de l'année an (nb entier). 
         sd=0 (=defaut): tous les jours fériés. 
         sd=1: idem sans les sammedis-dimanches. 
         sd=2: tous + les 2 jours fériés supplémentaires d'Alsace-Moselle. 
         sd=3: idem sd=2 sans les samedis-dimanches"""
    C = []
    J = []
    F, L = joursferiesliste(an, sd)
    for i in xrange(0,len(F)):
        C.append(datechaine(F[i]))  # conversion des dates-liste en dates-chaine
        J.append(joursem(F[i]))  # ajout du jour de semaine
    return C, J, L

Exemple d'utilisation: tous les jours fériés (sd=0, valeur par défaut)

F, J, L = joursferies(2009,0,'/')
for i in xrange(0,len(F)):
    print F[i], "%10s" % (J[i]), L[i]

Ce qui affiche:

01/01/2009      jeudi Jour de l'an
12/04/2009   dimanche Dimanche de Pâques
13/04/2009      lundi Lundi de Pâques
01/05/2009   vendredi Fête du travail
08/05/2009   vendredi Victoire des alliés 1945
21/05/2009      jeudi Jeudi de l'Ascension
31/05/2009   dimanche Dimanche de Pentecôte
01/06/2009      lundi Lundi de Pentecôte
14/07/2009      mardi Fête Nationale
15/08/2009     samedi Assomption
01/11/2009   dimanche Toussaint
11/11/2009   mercredi Armistice 1918
25/12/2009   vendredi Jour de Noël

Et sans les samedis-dimanches (sd=1):

F, J, L = joursferies(2009,1,'/')
for i in xrange(0,len(F)):
    print F[i], "%10s" % (J[i]), L[i]

Ce qui affiche:

01/01/2009      jeudi Jour de l'an
13/04/2009      lundi Lundi de Pâques
01/05/2009   vendredi Fête du travail
08/05/2009   vendredi Victoire des alliés 1945
21/05/2009      jeudi Jeudi de l'Ascension
01/06/2009      lundi Lundi de Pentecôte
14/07/2009      mardi Fête Nationale
11/11/2009   mercredi Armistice 1918
25/12/2009   vendredi Jour de Noël

Dit si une date est fériée France

Dit si une date d=[j,m,a] est fériée France:

  • si la date est fériée, renvoie son libellé (ex: “Jour de l'an”)
  • sinon, renvoie une chaine vide

Le paramètre sd a la même signification que précédemment, mais il ne faut pas se tromper avec la date qu'on donne: si on met un jour férié tombant un samedi avec sd=1, le verdict sera: non férié.

def estferie(d,sd=0):
    """estferie(d,sd=0): => dit si une date d=[j,m,a] donnée est fériée France
       si la date est fériée, renvoie son libellé
       sinon, renvoie une chaine vide"""
    j,m,a = d
    F, L = joursferiesliste(a, sd)
    for i in xrange(0, len(F)):
        if j==F[i][0] and m==F[i][1] and a==F[i][2]:
            return L[i]
    return ""    

Exemple d'utilisation:

print estferie([1,1,2009])
Jour de l'an

print estferie([2,1,2009])
                             <= chaine vide

print estferie([10,4,2009],sd=3)
Vendredi saint

calculer le nombre de jours ouvrés France entre 2 dates

Le principe est simple: on part d'une 1ère date d1, et on teste toutes les dates une à une jusqu'à d2. On incrémente un compteur uniquement si la date testée n'est ni un samedi, ni un dimanche, ni un jour férié. On renvoie le compteur à la fin

def nbjoursouvres(d1,d2,sd=1):
    """Calcule le nombre de jours ouvrés entre 2 dates (format d=[j,m,a]). 
       d1 doit être une date antérieure à d2
       d1 et d2, bornes de l'intervalle d1->d2, sont testés
       sd==1: élimination des samedis, dimanches et jours fériés
       sd==3: idem pour l'Alsace-Moselle
       sd=0 et sd=2 n'ont pas de sens ici
       """
    j1, m1, a1 = d1
    j2, m2, a2 = d2
    F, L = joursferiesliste(a1, sd)
    n = 0
    d = [j1, m1, a1]
    while True:
        if (d not in F) and numjoursem(d)<6:
            n += 1
        if d[0]==j2 and d[1]==m2 and d[2]==a2:
            break
        d = jourplus(d, +1)
        if d[2]!=a2:
            a2 = d[2]
            F, L = joursferiesliste(a2, sd)
    return n    

Exemple:

print nbjoursouvres([29,4,2009],[5,5,2009],sd=1)
4

print nbjoursouvres([24,12,2009],[2,1,2010],sd=1)
5

date_de_paques.txt · Dernière modification: 2009/10/13 12:33 par tyrtamos

Outils de la page