FIX caluclation of open days must not depends on TZ.

This commit is contained in:
Laurent Destailleur 2020-12-05 17:41:05 +01:00
parent 6023f2e16f
commit 6c2d520e21

View File

@ -597,10 +597,24 @@ function dol_get_first_day_week($day, $month, $year, $gm = false)
return array('year' => $year, 'month' => $month, 'week' => $week, 'first_day' => $tmpday, 'first_month' => $tmpmonth, 'first_year' => $tmpyear, 'prev_year' => $prev_year, 'prev_month' => $prev_month, 'prev_day' => $prev_day); return array('year' => $year, 'month' => $month, 'week' => $week, 'first_day' => $tmpday, 'first_month' => $tmpmonth, 'first_year' => $tmpyear, 'prev_year' => $prev_year, 'prev_month' => $prev_month, 'prev_day' => $prev_day);
} }
/**
* Return the easte day in GMT time.
* This function replaces easter_date() that returns a date in local TZ.
*
* @param int $year Year
* @return int GMT Date
*/
function getGMTEasterDatetime($year) {
$base = new DateTime("$year-03-21");
$days = easter_days($year); // Return number of days between 21 march and easter day.
$tmp = $base->add(new DateInterval("P{$days}D"));
return $tmp->getTimestamp();
}
/** /**
* Return the number of non working days including saturday and sunday (or not) between 2 dates in timestamp. * Return the number of non working days including saturday and sunday (or not) between 2 dates in timestamp.
* Dates must be UTC with hour, day, min to 0. * Dates must be UTC with hour, day, min to 0.
* Called by function num_open_day * Called by function num_open_day()
* *
* @param int $timestampStart Timestamp de debut * @param int $timestampStart Timestamp de debut
* @param int $timestampEnd Timestamp de fin * @param int $timestampEnd Timestamp de fin
@ -616,7 +630,6 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
global $db, $conf, $mysoc; global $db, $conf, $mysoc;
$nbFerie = 0; $nbFerie = 0;
$specialdayrule = array();
// Check to ensure we use correct parameters // 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 ((($timestampEnd - $timestampStart) % 86400) != 0) return 'Error Dates must use same hours and must be GMT dates';
@ -626,20 +639,23 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
if ($includesaturday < 0) $includesaturday = (isset($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY) ? $conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY : 1); if ($includesaturday < 0) $includesaturday = (isset($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY) ? $conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY : 1);
if ($includesunday < 0) $includesunday = (isset($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY) ? $conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY : 1); if ($includesunday < 0) $includesunday = (isset($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY) ? $conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY : 1);
$country_id = dol_getIdFromCode($db, $country_code, 'c_country', 'code', 'rowid');
$i = 0; $i = 0;
while ((($lastday == 0 && $timestampStart < $timestampEnd) || ($lastday && $timestampStart <= $timestampEnd)) 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) && ($i < 50000)) // Loop end when equals (Test on i is a security loop to avoid infinite loop)
{ {
$ferie = false; $ferie = false;
$specialdayrule = array();
$jour = date("d", $timestampStart); $jour = gmdate("d", $timestampStart);
$mois = date("m", $timestampStart); $mois = gmdate("m", $timestampStart);
$annee = date("Y", $timestampStart); $annee = gmdate("Y", $timestampStart);
$country_id = dol_getIdFromCode($db, $country_code, 'c_country', 'code', 'rowid'); //print "jour=".$jour." month=".$mois." year=".$annee." includesaturday=".$includesaturday." includesunday=".$includesunday."\n";
// Loop on public holiday defined into hrm_public_holiday // Loop on public holiday defined into hrm_public_holiday for the day, month and year analyzed
// TODO Execute this request first and store results into an array, then reuse this array.
$sql = "SELECT code, entity, fk_country, dayrule, year, month, day, active"; $sql = "SELECT code, entity, fk_country, dayrule, year, month, day, active";
$sql .= " FROM ".MAIN_DB_PREFIX."c_hrm_public_holiday"; $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 .= " WHERE active = 1 and fk_country IN (0".($country_id > 0 ? ", ".$country_id : 0).")";
@ -671,139 +687,147 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
dol_syslog($db->lasterror(), LOG_ERR); dol_syslog($db->lasterror(), LOG_ERR);
return 'Error sql '.$db->lasterror(); return 'Error sql '.$db->lasterror();
} }
//var_dump($specialdayrule)."\n";
//print "ferie=".$ferie."\n";
// Special dayrules if (!$ferie) {
if (in_array('easter', $specialdayrule)) // Special dayrules
{ if (in_array('easter', $specialdayrule))
// Calculation for easter date {
$date_paques = easter_date($annee); // Calculation for easter date
$jour_paques = date("d", $date_paques); $date_paques = getGMTEasterDatetime($annee);
$mois_paques = date("m", $date_paques); $jour_paques = gmdate("d", $date_paques);
if ($jour_paques == $jour && $mois_paques == $mois) $ferie = true; $mois_paques = gmdate("m", $date_paques);
// Easter (sunday) if ($jour_paques == $jour && $mois_paques == $mois) $ferie = true;
} // Easter (sunday)
}
if (in_array('eastermonday', $specialdayrule)) if (in_array('eastermonday', $specialdayrule))
{ {
// Calculation for the monday of easter date // Calculation for the monday of easter date
$date_paques = easter_date($annee); $date_paques = getGMTEasterDatetime($annee);
$date_lundi_paques = mktime( $date_lundi_paques = mktime(
date("H", $date_paques), gmdate("H", $date_paques),
date("i", $date_paques), gmdate("i", $date_paques),
date("s", $date_paques), gmdate("s", $date_paques),
date("m", $date_paques), gmdate("m", $date_paques),
date("d", $date_paques) + 1, gmdate("d", $date_paques) + 1,
date("Y", $date_paques) gmdate("Y", $date_paques)
);
$jour_lundi_ascension = date("d", $date_lundi_paques);
$mois_lundi_ascension = date("m", $date_lundi_paques);
if ($jour_lundi_ascension == $jour && $mois_lundi_ascension == $mois) $ferie = true;
// Easter (monday)
}
if (in_array('ascension', $specialdayrule))
{
// Calcul du jour de l'ascension (39 days after easter day)
$date_paques = easter_date($annee);
$date_ascension = mktime(
date("H", $date_paques),
date("i", $date_paques),
date("s", $date_paques),
date("m", $date_paques),
date("d", $date_paques) + 39,
date("Y", $date_paques)
);
$jour_ascension = date("d", $date_ascension);
$mois_ascension = date("m", $date_ascension);
if ($jour_ascension == $jour && $mois_ascension == $mois) $ferie = true;
// Ascension (thursday)
}
if (in_array('pentecote', $specialdayrule))
{
// Calculation of "Pentecote" (49 days after easter day)
$date_paques = easter_date($annee);
$date_pentecote = mktime(
date("H", $date_paques),
date("i", $date_paques),
date("s", $date_paques),
date("m", $date_paques),
date("d", $date_paques) + 49,
date("Y", $date_paques)
);
$jour_pentecote = date("d", $date_pentecote);
$mois_pentecote = date("m", $date_pentecote);
if ($jour_pentecote == $jour && $mois_pentecote == $mois) $ferie = true;
// "Pentecote" (sunday)
}
if (in_array('pentecotemonday', $specialdayrule))
{
// Calculation of "Pentecote" (49 days after easter day)
$date_paques = easter_date($annee);
$date_pentecote = mktime(
date("H", $date_paques),
date("i", $date_paques),
date("s", $date_paques),
date("m", $date_paques),
date("d", $date_paques) + 50,
date("Y", $date_paques)
); );
$jour_pentecote = date("d", $date_pentecote); $jour_lundi_paques = gmdate("d", $date_lundi_paques);
$mois_pentecote = date("m", $date_pentecote); $mois_lundi_paques = gmdate("m", $date_lundi_paques);
if ($jour_pentecote == $jour && $mois_pentecote == $mois) $ferie = true; if ($jour_lundi_paques == $jour && $mois_lundi_paques == $mois) $ferie = true;
// "Pentecote" (monday) // Easter (monday)
} }
if (in_array('viernessanto', $specialdayrule)) if (in_array('ascension', $specialdayrule))
{ {
// Viernes Santo // Calcul du jour de l'ascension (39 days after easter day)
$date_paques = easter_date($annee); $date_paques = getGMTEasterDatetime($annee);
$date_viernes = mktime( $date_ascension = mktime(
date("H", $date_paques), gmdate("H", $date_paques),
date("i", $date_paques), gmdate("i", $date_paques),
date("s", $date_paques), gmdate("s", $date_paques),
date("m", $date_paques), gmdate("m", $date_paques),
date("d", $date_paques) - 2, gmdate("d", $date_paques) + 39,
date("Y", $date_paques) gmdate("Y", $date_paques)
);
$jour_viernes = date("d", $date_viernes);
$mois_viernes = date("m", $date_viernes);
if ($jour_viernes == $jour && $mois_viernes == $mois) $ferie = true;
//Viernes Santo
}
if (in_array('fronleichnam', $specialdayrule))
{
// Fronleichnam (60 days after easter sunday)
$date_paques = easter_date($annee);
$date_fronleichnam = mktime(
date("H", $date_paques),
date("i", $date_paques),
date("s", $date_paques),
date("m", $date_paques),
date("d", $date_paques) + 60,
date("Y", $date_paques)
); );
$jour_fronleichnam = date("d", $date_fronleichnam); $jour_ascension = gmdate("d", $date_ascension);
$mois_fronleichnam = date("m", $date_fronleichnam); $mois_ascension = gmdate("m", $date_ascension);
if ($jour_fronleichnam == $jour && $mois_fronleichnam == $mois) $ferie = true; if ($jour_ascension == $jour && $mois_ascension == $mois) $ferie = true;
// Fronleichnam // Ascension (thursday)
}
if (in_array('pentecote', $specialdayrule))
{
// Calculation of "Pentecote" (49 days after easter day)
$date_paques = getGMTEasterDatetime($annee);
$date_pentecote = mktime(
gmdate("H", $date_paques),
gmdate("i", $date_paques),
gmdate("s", $date_paques),
gmdate("m", $date_paques),
gmdate("d", $date_paques) + 49,
gmdate("Y", $date_paques)
);
$jour_pentecote = gmdate("d", $date_pentecote);
$mois_pentecote = gmdate("m", $date_pentecote);
if ($jour_pentecote == $jour && $mois_pentecote == $mois) $ferie = true;
// "Pentecote" (sunday)
}
if (in_array('pentecotemonday', $specialdayrule))
{
// Calculation of "Pentecote" (49 days after easter day)
$date_paques = getGMTEasterDatetime($annee);
$date_pentecote = mktime(
gmdate("H", $date_paques),
gmdate("i", $date_paques),
gmdate("s", $date_paques),
gmdate("m", $date_paques),
gmdate("d", $date_paques) + 50,
gmdate("Y", $date_paques)
);
$jour_pentecote = gmdate("d", $date_pentecote);
$mois_pentecote = gmdate("m", $date_pentecote);
if ($jour_pentecote == $jour && $mois_pentecote == $mois) $ferie = true;
// "Pentecote" (monday)
}
if (in_array('viernessanto', $specialdayrule))
{
// Viernes Santo
$date_paques = getGMTEasterDatetime($annee);
$date_viernes = mktime(
gmdate("H", $date_paques),
gmdate("i", $date_paques),
gmdate("s", $date_paques),
gmdate("m", $date_paques),
gmdate("d", $date_paques) - 2,
gmdate("Y", $date_paques)
);
$jour_viernes = gmdate("d", $date_viernes);
$mois_viernes = gmdate("m", $date_viernes);
if ($jour_viernes == $jour && $mois_viernes == $mois) $ferie = true;
//Viernes Santo
}
if (in_array('fronleichnam', $specialdayrule))
{
// Fronleichnam (60 days after easter sunday)
$date_paques = getGMTEasterDatetime($annee);
$date_fronleichnam = mktime(
gmdate("H", $date_paques),
gmdate("i", $date_paques),
gmdate("s", $date_paques),
gmdate("m", $date_paques),
gmdate("d", $date_paques) + 60,
gmdate("Y", $date_paques)
);
$jour_fronleichnam = gmdate("d", $date_fronleichnam);
$mois_fronleichnam = gmdate("m", $date_fronleichnam);
if ($jour_fronleichnam == $jour && $mois_fronleichnam == $mois) $ferie = true;
// Fronleichnam
}
} }
//print "ferie=".$ferie."\n";
// If we have to include saturday and sunday // If we have to include saturday and sunday
if ($includesaturday || $includesunday) if (!$ferie) {
{ if ($includesaturday || $includesunday)
$jour_julien = unixtojd($timestampStart);
$jour_semaine = jddayofweek($jour_julien, 0);
if ($includesaturday) //Saturday (6) and Sunday (0)
{ {
if ($jour_semaine == 6) $ferie = true; $jour_julien = unixtojd($timestampStart);
} $jour_semaine = jddayofweek($jour_julien, 0);
if ($includesunday) //Saturday (6) and Sunday (0) if ($includesaturday) //Saturday (6) and Sunday (0)
{ {
if ($jour_semaine == 0) $ferie = true; if ($jour_semaine == 6) $ferie = true;
}
if ($includesunday) //Saturday (6) and Sunday (0)
{
if ($jour_semaine == 0) $ferie = true;
}
} }
} }
//print "ferie=".$ferie."\n";
// We increase the counter of non working day // We increase the counter of non working day
if ($ferie) $nbFerie++; if ($ferie) $nbFerie++;
@ -815,6 +839,7 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
$i++; $i++;
} }
//print "nbFerie=".$nbFerie."\n";
return $nbFerie; return $nbFerie;
} }