Trouver les jours fériés français en PHP

Calculer le nombre de jours ouvrés entre deux dates.

07 octobre 2012

Toutes les entreprises françaises ont eu un jour besoin de calculer le nombre de jours ouvrés entre deux dates. Certains sont très faciles à calculer, d'autres dépendent du jour de pâques et changent donc tous les ans. Dans ce tutoriel nous irons par étapes : nous apprendrons à trouver le jour de Pâques, nous ferons une liste des jours fériés français et pour finir nous calculerons le nombre de jours ouvrés entre deux dates.

Trouver le jour de pâques en programmation

En PHP la solution à ce problème est très simple, la fonction easter_date fait tout le travail pour nous.

La fonction easter_date

echo date("d/m/Y", easter_date(2012));
/* Sortie : 08/04/2012 */

Toutefois, comme je suis gentil , je vais vous donner une fonction détaillée que vous pourrez adapter à n'importe quel langage. Cette fonction est tirée d'un algorithme de Oudin. Par définition pâques représente : le premier dimanche qui suit la première pleine lune qui suit le (ou est égal au) premier jour du printemps (21 mars). Minute culturelle : pâques symbolise la résurrection de Jésus.

Algorithme pour calculer pâques

$year = 2012;

$a = $year % 4;
$b = $year % 7;
$c = $year % 19;
$m = 24;
$n = 5;
$d = (19 * $c + $m ) % 30;
$e = (2 * $a + 4 * $b + 6 * $d + $n) % 7;

$easterdate = 22 + $d + $e;

if ($easterdate > 31)
{
        $day = $d + $e - 9;
        $month = 4;
}
else
{
        $day = 22 + $d + $e;
        $month = 3;
}

if ($d == 29 && $e == 6)
{
        $day = 10;
        $month = 04;
}
elseif ($d == 28 && $e == 6)
{
        $day = 18;
        $month = 04;
}

echo $day.'/'.$month.'/'.$year;
/* Sortie : 8/4/2012 */


/* Pour obtenir un timestamp. */
echo mktime(0, 0, 0, $month, $day, $year);
/* Sortie : 1333836000 */

Liste des jours fériés français

  • Jour de l'an : 1er janvier
  • Fête du travail : 1er mai
  • Victoire des alliés 1945 : 8 mai
  • Fête nationale, anniversaire de la fête de la fédération : 14 juillet
  • Assomption, fin de la vie terrestre de Marie : 15 août
  • Toussaint, fête de tous les saints : 1er novembre
  • Armistice de 1918 : 11 novembre
  • Noël : 25 décembre
  • Lundi de pâques : dimanche de pâques + 1
  • Ascension, élévation de Jésus : dimanche de pâques + 39
  • Pentecôte, venue du Saint Esprit : dimanche de pâques + 50

Liste des jours fériés français en PHP

public static function getHolidays($year = null)
{
        if ($year === null)
        {
                $year = intval(strftime('%Y'));
        }

        $easterDate = easter_date($year);
        $easterDay = date('j', $easterDate);
        $easterMonth = date('n', $easterDate);
        $easterYear = date('Y', $easterDate);

        $holidays = array(
                // Jours feries fixes
                mktime(0, 0, 0, 1, 1, $year),// 1er janvier
                mktime(0, 0, 0, 5, 1, $year),// Fete du travail
                mktime(0, 0, 0, 5, 8, $year),// Victoire des allies
                mktime(0, 0, 0, 7, 14, $year),// Fete nationale
                mktime(0, 0, 0, 8, 15, $year),// Assomption
                mktime(0, 0, 0, 11, 1, $year),// Toussaint
                mktime(0, 0, 0, 11, 11, $year),// Armistice
                mktime(0, 0, 0, 12, 25, $year),// Noel

                // Jour feries qui dependent de paques
                mktime(0, 0, 0, $easterMonth, $easterDay + 1, $easterYear),// Lundi de paques
                mktime(0, 0, 0, $easterMonth, $easterDay + 39, $easterYear),// Ascension
                mktime(0, 0, 0, $easterMonth, $easterDay + 50, $easterYear), // Pentecote
        );

        sort($holidays);

        return $holidays;
}

print_r (InformatixDate::getHolidays(2012));

/* Sortie :
Array
(
        [0] => 1325372400
        [1] => 1333922400
        [2] => 1335823200
        [3] => 1336428000
        [4] => 1337205600
        [5] => 1338156000
        [6] => 1342216800
        [7] => 1344981600
        [8] => 1351724400
        [9] => 1352588400
        [10] => 1356390000
)
*/

Calculer le nombre de jours ouvrés entre deux dates

Maintenant que nous connaissons les jours fériés, il suffit de connaître le nombre de jours entre deux dates et de soustraire les jours fériés ainsi que les week end.

Nombre de jours calendaires entre deux dates

public static function diffCalendar($firstDate, $secondDate)
{
        $oFirstDate = new DateTime($firstDate);
        $oSecondDate = new DateTime($secondDate);

        return (integer) ($oSecondDate->getTimestamp() - $oFirstDate->getTimestamp());
}

echo InformatixDate::diffCalendar('2012-10-04', '2012-10-14') / 86400;
/* Sortie : 10 */

Nombre de jours ouvrés entre deux dates

public static function diffWorkDay($firstDate, $secondDate)
{
        /*
         * Pour calculer le nombre de jours ouvres,
         * on calcule le nombre total de jours et
         * on soustrait les jours fériés et les week end.
         */

        $iDiffCalendar = self::diffCalendar($firstDate, $secondDate);

        $oFirstDate = new DateTime($firstDate);
        $oSecondDate = new DateTime($secondDate);

        $iFirstYear = $oFirstDate->format('Y');
        $iSecondYear = $oSecondDate->format('Y');

        $aHolidays = array();

        /*
         * Si l'interval demande chevauche plusieurs annees
         * on doit avoir les jours feries de toutes ces annees
         */

        for ($iYear = $iFirstYear; $iYear <= $iSecondYear; $iYear++)
        {
                $aHolidays = array_merge(self::getHolidays($iYear), $aHolidays);
        }

        /*
         * On est oblige de convertir les timestamps en string a cause des decalages horaires.
         */

        $aHolidaysString = array_map(function ($value)
        {
                return strftime('%Y-%m-%d', $value);
        }, $aHolidays);

        for ($i = $oFirstDate->getTimestamp(); $i < $oSecondDate->getTimestamp(); $i += 86400)
        {
                /* Numero du jour de la semaine, de 1 pour lundi a 7 pour dimanche */
                $iDayNum = strftime('%u', $i);

                if (in_array(strftime('%Y-%m-%d', $i), $aHolidaysString) OR $iDayNum == 6 OR $iDayNum == 7)
                {
                        /* Si c'est ferie ou samedi ou dimanche, on soustrait le nombre de secondes dans une journee. */
                        $iDiffCalendar -= 86400;
                }
        }

        return (integer) $iDiffCalendar;
}

echo InformatixDate::diffWorkDay('2012-10-04', '2012-10-14') / 86400;
/* Sortie : 7 */

Et voilà ! vous pouvez maintenant calculer le nombre de jours ouvrés entre deux dates. Comme je suis un type sympa, je vous donne en bonus deux fonctions utiles que vous n'auriez normalement eus aucun mal à faire à l'aide des fonctions précédentes.

Tester si une date est un jour férié ou un week end

public static function isHoliday($timestamp)
{
        $iDayNum = strftime('%u', $timestamp);
        $iYear = strftime('%Y', $timestamp);

        $aHolidays = self::getHolidays($iYear);

        /*
        * On est oblige de convertir les timestamps en string a cause des decalages horaires.
        */

        $aHolidaysString = array_map(function ($value)
        {
                return strftime('%Y-%m-%d', $value);
        }, $aHolidays);

        if (in_array(strftime('%Y-%m-%d', $timestamp), $aHolidaysString) OR $iDayNum == 6 OR $iDayNum == 7)
        {
                return true;
        }

        return false;
}

Tester si une date est un jour ouvré

public static function isWorkingDay($timestamp)
{
        return (!self::isHoliday($timestamp));
}

Merci d'avoir suivi ce tutoriel. Toutes ces fonctions sont faites "maison" (sauf certaines parties inspirées d'autres codes) et la possibilité d'un bug n'est donc pas nulle, j'attends vos retours dans les commentaires.

A bientôt !

Par
Créateur et administrateur.

Dans la même catégorie

Formater un tableau pour CURLOPT_POSTFIELDS
Email avec pièce jointe en PHP
PHP : modifier les attributs privés d'un objet
Tester l'existence d'un fichier dans l'include path
Convertir récursivement un objet PHP en tableau
PHP : formater un tableau en CSV
Comment envoyer un mail en ligne de commande ?
RSYNC : Comment synchroniser des fichiers à travers une connexion ssh ?
Exécuter un code PHP en ligne de commande
Doctrine 2 : générer les classes PHP depuis la base de données
Comment catcher les erreurs en PHP ?
Doctrine 2 : comment afficher la requête SQL ?
Comment construire une URL sans caractères spéciaux en PHP ?
Comment lister les fichiers PHP inclus sur ma page ?
Les fonctions anonymes récursives en PHP
Requête HTTP asynchrone en PHP
La résolution statique à la volée ou Late Static Bindings
Comment allumer son ordinateur à distance en PHP ?
Comment utiliser la balise meta viewport ?
Une version mobile de mon site avec le Zend Framework
Doctrine et le Zend Framework : Présentation, intégration et utilisation
Créer son flux RSS simplement avec Zend_Feed
Appliquer un layout sur un mail avec le Zend Framework
Comment lancer une requête multi-bases avec les fonctions MySQL ?
Implode / Explode : Du tableau à la chaine de caractères, de la chaine de caractères au tableau

Commentaire(s)