Skip to content

Commit

Permalink
feat: add function to get public holidays list within period
Browse files Browse the repository at this point in the history
  • Loading branch information
chloegregoirecufi committed Dec 24, 2024
1 parent e217cd6 commit d2a673d
Showing 1 changed file with 277 additions and 0 deletions.
277 changes: 277 additions & 0 deletions htdocs/core/lib/date.lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,283 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
return $nbFerie;
}

/**
* Return the list of public holidays including Friday, Saturday and Sunday (or not) between 2 dates in timestamp.
* Dates must be UTC with hour, min, sec to 0.
* Called by function num_open_day()
*
* @param int $timestampStart Timestamp start (UTC with hour, min, sec = 0)
* @param int $timestampEnd Timestamp end (UTC with hour, min, sec = 0)
* @param string $country_code Country code
* @param int $lastday Last day is included, 0: no, 1:yes
* @param int $excludesaturday Exclude saturday as non working day (-1=use setup, 0=no, 1=yes)
* @param int $excludesunday Exclude sunday as non working day (-1=use setup, 0=no, 1=yes)
* @param int $excludefriday Exclude friday as non working day (-1=use setup, 0=no, 1=yes)
* @param int $excludemonday Exclude monday as non working day (-1=use setup, 0=no, 1=yes)
* @return int|array List of public holidays or error message string if error
* @see num_between_day(), num_open_day()
*/
function list_public_holiday($timestampStart, $timestampEnd, $country_code = '', $lastday = 0, $excludesaturday = -1, $excludesunday = -1, $excludefriday = -1, $excludemonday = -1)
{
global $conf, $db, $mysoc;

// Check to ensure we use correct parameters
if (($timestampEnd - $timestampStart) % 86400 != 0) {
return 'Error Dates must use same hours and must be GMT dates';
}

if (empty($country_code)) {
$country_code = $mysoc->country_code;
}
if ($excludemonday < 0) {
$excludemonday = getDolGlobalInt('MAIN_NON_WORKING_DAYS_INCLUDE_MONDAY', 0);
}
if ($excludefriday < 0) {
$excludefriday = getDolGlobalInt('MAIN_NON_WORKING_DAYS_INCLUDE_FRIDAY', 0);
}
if ($excludesaturday < 0) {
$excludesaturday = getDolGlobalInt('MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY', 1);
}
if ($excludesunday < 0) {
$excludesunday = getDolGlobalInt('MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY', 1);
}

$country_id = dol_getIdFromCode($db, $country_code, 'c_country', 'code', 'rowid');

if (empty($conf->cache['arrayOfActivePublicHolidays_' . $country_id])) {
// Loop on public holiday defined into hrm_public_holiday for the day, month and year analyzed
$tmpArrayOfPublicHolidays = array();
$sql = "SELECT id, code, entity, fk_country, dayrule, year, month, day, active";
$sql .= " FROM " . MAIN_DB_PREFIX . "c_hrm_public_holiday";
$sql .= " WHERE active = 1 and fk_country IN (0" . ($country_id > 0 ? ", " . $country_id : 0) . ")";
$sql .= " AND entity IN (0," . getEntity('holiday') . ")";

$resql = $db->query($sql);
if ($resql) {
$num_rows = $db->num_rows($resql);
$i = 0;
while ($i < $num_rows) {
$obj = $db->fetch_object($resql);
$tmpArrayOfPublicHolidays[$obj->id] = array('dayrule' => $obj->dayrule, 'year' => $obj->year, 'month' => $obj->month, 'day' => $obj->day);
$i++;
}
} else {
dol_syslog($db->lasterror(), LOG_ERR);
return 'Error sql ' . $db->lasterror();
}

//var_dump($tmpArrayOfPublicHolidays);
$conf->cache['arrayOfActivePublicHolidays_' . $country_id] = $tmpArrayOfPublicHolidays;
}

$arrayOfPublicHolidays = $conf->cache['arrayOfActivePublicHolidays_' . $country_id];
$listFeries = [];
$i = 0;
while ((($lastday == 0 && $timestampStart < $timestampEnd) || ($lastday && $timestampStart <= $timestampEnd))
&& ($i < 50000)) { // Loop end when equals (Test on i is a security loop to avoid infinite loop)
$nonWorkingDay = false;
$ferie = false;
$specialdayrule = array();

$jour = (int)gmdate("d", $timestampStart);
$mois = (int)gmdate("m", $timestampStart);
$annee = (int)gmdate("Y", $timestampStart);

// If we have to exclude Friday, Saturday and Sunday
if ($excludefriday || $excludesaturday || $excludesunday) {
$jour_julien = unixtojd($timestampStart);
$jour_semaine = jddayofweek($jour_julien, 0);
if ($excludefriday) { //Friday (5), Saturday (6) and Sunday (0)
if ($jour_semaine == 5) {
$nonWorkingDay = true;
}
}
if ($excludesaturday) { //Friday (5), Saturday (6) and Sunday (0)
if ($jour_semaine == 6) {
$nonWorkingDay = true;
}
}
if ($excludesunday) { //Friday (5), Saturday (6) and Sunday (0)
if ($jour_semaine == 0) {
$nonWorkingDay = true;
}
}
}
//print "ferie=".$nonWorkingDay."\n";

if (!$nonWorkingDay) {
//print "jour=".$jour." month=".$mois." year=".$annee." includesaturday=".$excludesaturday." includesunday=".$excludesunday."\n";
foreach ($arrayOfPublicHolidays as $entrypublicholiday) {
if (!empty($entrypublicholiday['dayrule']) && $entrypublicholiday['dayrule'] != 'date') { // For example 'easter', '...'
$specialdayrule[$entrypublicholiday['dayrule']] = $entrypublicholiday['dayrule'];
} else {
$match = 1;
if (!empty($entrypublicholiday['year']) && $entrypublicholiday['year'] != $annee) {
$match = 0;
}
if ($entrypublicholiday['month'] != $mois) {
$match = 0;
}
if ($entrypublicholiday['day'] != $jour) {
$match = 0;
}

if ($match) {
$ferie = true;
$listFeries[] = $timestampStart;
}
}

$i++;
}
//var_dump($specialdayrule)."\n";
//print "ferie=".$nonWorkingDay."\n";
}

if (!$nonWorkingDay && !$ferie) {
// Special dayrules
if (in_array('easter', $specialdayrule)) {
// Calculation for easter date
$date_paques = getGMTEasterDatetime($annee);
$jour_paques = gmdate("d", $date_paques);
$mois_paques = gmdate("m", $date_paques);
if ($jour_paques == $jour && $mois_paques == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
// Easter (sunday)
}

if (in_array('eastermonday', $specialdayrule)) {
// Calculation for the monday of easter date
$date_paques = getGMTEasterDatetime($annee);
//print 'PPP'.$date_paques.' '.dol_print_date($date_paques, 'dayhour', 'gmt')." ";
$date_lundi_paques = $date_paques + (3600 * 24);
$jour_lundi_paques = gmdate("d", $date_lundi_paques);
$mois_lundi_paques = gmdate("m", $date_lundi_paques);
if ($jour_lundi_paques == $jour && $mois_lundi_paques == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
// Easter (monday)
//print 'annee='.$annee.' $jour='.$jour.' $mois='.$mois.' $jour_lundi_paques='.$jour_lundi_paques.' $mois_lundi_paques='.$mois_lundi_paques."\n";
}

//Good Friday
if (in_array('goodfriday', $specialdayrule)) {
// Pulls the date of Easter
$easter = getGMTEasterDatetime($annee);

// Calculates the date of Good Friday based on Easter
$date_good_friday = $easter - (2 * 3600 * 24);
$dom_good_friday = gmdate("d", $date_good_friday);
$month_good_friday = gmdate("m", $date_good_friday);

if ($dom_good_friday == $jour && $month_good_friday == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
}

if (in_array('ascension', $specialdayrule)) {
// Calcul du jour de l'ascension (39 days after easter day)
$date_paques = getGMTEasterDatetime($annee);
$date_ascension = $date_paques + (3600 * 24 * 39);
$jour_ascension = gmdate("d", $date_ascension);
$mois_ascension = gmdate("m", $date_ascension);
if ($jour_ascension == $jour && $mois_ascension == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
// Ascension (thursday)
}

if (in_array('pentecost', $specialdayrule)) {
// Calculation of "Pentecote" (49 days after easter day)
$date_paques = getGMTEasterDatetime($annee);
$date_pentecote = $date_paques + (3600 * 24 * 49);
$jour_pentecote = gmdate("d", $date_pentecote);
$mois_pentecote = gmdate("m", $date_pentecote);
if ($jour_pentecote == $jour && $mois_pentecote == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
// "Pentecote" (sunday)
}

if (in_array('pentecotemonday', $specialdayrule)) {
// Calculation of "Pentecote" (49 days after easter day)
$date_paques = getGMTEasterDatetime($annee);
$date_pentecote = $date_paques + (3600 * 24 * 50);
$jour_pentecote = gmdate("d", $date_pentecote);
$mois_pentecote = gmdate("m", $date_pentecote);
if ($jour_pentecote == $jour && $mois_pentecote == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
// "Pentecote" (monday)
}

if (in_array('viernessanto', $specialdayrule)) {
// Viernes Santo
$date_paques = getGMTEasterDatetime($annee);
$date_viernes = $date_paques - (3600 * 24 * 2);
$jour_viernes = gmdate("d", $date_viernes);
$mois_viernes = gmdate("m", $date_viernes);
if ($jour_viernes == $jour && $mois_viernes == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
//Viernes Santo
}

if (in_array('fronleichnam', $specialdayrule)) {
// Fronleichnam (60 days after easter sunday)
$date_paques = getGMTEasterDatetime($annee);
$date_fronleichnam = $date_paques + (3600 * 24 * 60);
$jour_fronleichnam = gmdate("d", $date_fronleichnam);
$mois_fronleichnam = gmdate("m", $date_fronleichnam);
if ($jour_fronleichnam == $jour && $mois_fronleichnam == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
// Fronleichnam
}

if (in_array('genevafast', $specialdayrule)) {
// Geneva fast in Switzerland (Thursday after the first sunday in September)
$date_1sunsept = strtotime('next thursday', strtotime('next sunday', mktime(0, 0, 0, 9, 1, $annee)));
$jour_1sunsept = date("d", $date_1sunsept);
$mois_1sunsept = date("m", $date_1sunsept);
if ($jour_1sunsept == $jour && $mois_1sunsept == $mois) {
$ferie = true;
$listFeries[] = $timestampStart;

}
// Geneva fast in Switzerland
}
}
//print "ferie=".$nonWorkingDay."\n";

// Increase number of days (on go up into loop)
$timestampStart = dol_time_plus_duree($timestampStart, 1, 'd');
//var_dump($jour.' '.$mois.' '.$annee.' '.$timestampStart);

$i++;
}

//print "nbFerie=".$nbFerie."\n";
return $listFeries;
}

/**
* Function to return number of days between two dates (date must be UTC date !)
* Example: 2012-01-01 2012-01-02 => 1 if lastday=0, 2 if lastday=1
Expand Down

0 comments on commit d2a673d

Please sign in to comment.