Ajouter des jours ouvrés à une date en PHP

L'ajout d'un nombre de jours ouvrés à une date peut-être réalisé de différentes façons, plus ou moins complexe. Dans ce billet, je vous livre quelques méthodes de calculs permettant d'ajouter un nombre de jours ouvrés à une date.

Il est important de différencier et de définir les jours ouvrés des jours ouvrables :

  • un jour ouvré est un jour effectivement travaillé dans une entreprise ou une administration. On compte 5 jours ouvrés par semaine. En fonction de l'organisation ce sont les jours du lundi au vendredi ou du mardi au samedi.
  • un jour ouvrable correspond à tous les jours de la semaine, à l'exception du jour de repos hebdomadaire (généralement le dimanche) et des jours fériés habituellement non travaillés dans l'entreprise.

 

Méthode la plus simple et efficace

La méthode la plus simple et efficace consiste à utiliser la fonction strtotime() en utilisant le format de date weekdays.

Attention : weekdays représente uniquement les jours compris entre le lundi et le vendredi.

Par exemple, pour ajouter 3 jours ouvrés :

echo date ( 'Y-m-d' , strtotime ( '3 weekdays' ) );

Exemple de fonction :

function date_addWorkingDays( $date_ts, $workingDays) {
    return strtotime ( $workingDays . ' weekdays' , $date_ts );
}



echo date( "Y-m-d" , date_addWorkingDays( strtotime("2017-12-13"), 5 ) );
// retourne : 2017-12-20

echo date( "Y-m-d" , date_addWorkingDays( strtotime("2016-02-25"), 7 ) );
// retourne : 2016-03-07

 

Pour prendre en compte les jours fériés, il suffit d'intégrer un tableau contenant les jours féries puis,

  • d'ajouter les jours ouvrés un à un,
  • de vérifier que le jour ajouté n'est pas un jour férié
  • et d'ajuster le nombre de jours à ajouter en conséquence

 

function date_getArrayHolidays( $year = null , $format = "Y-m-d" ) {
    if ($year === null) {
        $year = intval(date('Y'));
    }

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

    $holidays = array(
        // Dates fixes
        date( $format, mktime(0, 0, 0, 1,  1,  $year)),  // 1er janvier
        date( $format, mktime(0, 0, 0, 5,  1,  $year)),  // Fête du travail
        date( $format, mktime(0, 0, 0, 5,  8,  $year)),  // Victoire des alliés
        date( $format, mktime(0, 0, 0, 7,  14, $year)),  // Fête nationale
        date( $format, mktime(0, 0, 0, 8,  15, $year)),  // Assomption
        date( $format, mktime(0, 0, 0, 11, 1,  $year)),  // Toussaint
        date( $format, mktime(0, 0, 0, 11, 11, $year)),  // Armistice
        date( $format, mktime(0, 0, 0, 12, 25, $year)),  // Noel
        // Dates variables
        date( $format, mktime(0, 0, 0, $easterMonth, $easterDay + 1,  $easterYear)),  // Lundi de paques
        date( $format, mktime(0, 0, 0, $easterMonth, $easterDay + 39, $easterYear)),  // Jeudi de Ascension
        date( $format, mktime(0, 0, 0, $easterMonth, $easterDay + 50, $easterYear)),  // Lundi de Pentecôte
    );
    sort($holidays);
    return $holidays;  
}

function date_addWorkingDays( $date_ts, $workingDays) {
    // Tableau contenant les jours fériés
    $year = date("Y", $date_ts );
    $ary_holidays = array_merge( date_getArrayHolidays( $year , "Y-m-d" ) , date_getArrayHolidays( $year+1 , "Y-m-d" ) );

    // Ajout des jours ouvrés
    $i=0;
    while( $i < $workingDays) {
        $date_tmp = date( "Y-m-d" , strtotime ( $i . ' weekdays' , $date_ts ) );
        if( in_array( $date_tmp , $ary_holidays ) ) {
            $workingDays++;
        }
        $i++;
    }
    return strtotime ( $workingDays . ' weekdays' , $date_ts );
}



echo date( "Y-m-d" , date_addWorkingDays( strtotime("2017-07-11"), 5 ) );
// retourne : 2017-07-19

 

 

Méthode la plus souple

Cette fonction permet de définir les jours composants les weeks-ends et une heure limite. Elle permet de s'adapter aux différents cas de figures : jours ouvrés, jours ouvrables etc..

function date_AddWorkingDays( $date_ts , $workingDays, $time_limit = 16, $ary_WeekEnd = array(0,6) ) {
    // Tableau contenant les jours fériés
    $year = date("Y", $date_ts );
    $ary_holidays = array_merge( date_getArrayHolidays( $year , "Y-m-d" ) , date_getArrayHolidays( $year+1 , "Y-m-d" ) );

    // Ajustement du nombre de jours ouvrés à ajouter en fonction de l'heure limite
    if( !in_array( date('w', $date_ts) , $ary_WeekEnd ) && !in_array( date( "Y-m-d", $date_ts) , $ary_holidays ) && date( "G" , $date_ts ) >= $time_limit ) {
        $workingDays += 1;
    }
    // Ajustement du nombre de jours ouvrés à ajouter en fonction de la date de début
    if( in_array( date('w', $date_ts), $ary_WeekEnd ) || in_array( date( "Y-m-d", $date_ts) , $ary_holidays ) ) {
        $workingDays += 1;
    }

    // Ajout des jours ouvrés
    $i = 0;
    while( $i < $workingDays ) {
        $date_ts = strtotime( date("Y-m-d", $date_ts) . " +1 days");
        if( !in_array(date('w', $date_ts), $ary_WeekEnd ) && !in_array( date( "Y-m-d", $date_ts) , $ary_holidays ) ) {
            $i++;
        }
    }

    return $date_ts;
}


echo date( "Y-m-d" , date_addWorkingDays( strtotime("2017-12-11 15:10"), 4 ) );
// retourne : 2017-12-15

echo date( "Y-m-d" , date_addWorkingDays( strtotime("2017-12-11 15:59"), 4 ) );
// retoune : 2017-12-15

echo date( "Y-m-d" , date_addWorkingDays( strtotime("2017-12-11 16:00"), 4 ) );
// retourne : 2017-12-18


// Si nous définissons les jours ouvrés comme étant du mardi au samedi :
echo date( "Y-m-d" , date_addWorkingDays( strtotime("2017-12-11 15:10"), 4 , 16 , array(0,1) ) );
// retourne : 2017-12-16

echo date( "Y-m-d" , date_addWorkingDays( strtotime("2017-12-12 15:10"), 4 , 16 , array(0,1) ) );
// retourne : 2017-12-16

echo date( "Y-m-d" , date_addWorkingDays( strtotime("2017-12-12 16:00"), 4 , 16 , array(0,1) ) );
// retourne : 2017-12-19

 

Voilà !

Étiquettes
PHP