FIX dol_print_date with param gmt when server is not UTC.

This commit is contained in:
Laurent Destailleur
2025-10-24 15:30:02 +02:00
parent c6c968374a
commit eec7c592c0
4 changed files with 39 additions and 20 deletions

View File

@@ -115,7 +115,7 @@ function getServerTimeZoneInt($refgmtdate = 'now')
/**
* Add a delay to a date
*
* @param int $time Date timestamp
* @param int $time Date timestamp (Must be a UTC timestamp)
* @param float $duration_value Value of delay to add
* @param string $duration_unit Unit of added delay (d, m, y, w, h, i)
* @param int<0,1> $ruleforendofmonth Change the behavior of PHP over data-interval, 0 or 1
@@ -163,9 +163,11 @@ function dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforend
}
$date = new DateTime();
if (getDolGlobalString('MAIN_DATE_IN_MEMORY_ARE_GMT')) {
if (!function_exists('getDolGlobalString') || !getDolGlobalString('MAIN_DATE_IN_MEMORY_ARE_NOT_GMT')) { // Add function_exists to allow usage of this function with minimal context
$date->setTimezone(new DateTimeZone('UTC'));
}
$date->setTimestamp((int) $time);
$interval = new DateInterval($deltastring);
@@ -174,7 +176,8 @@ function dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforend
} else {
$date->add($interval);
}
//Change the behavior of PHP over data-interval when the result of this function is Feb 29 (non-leap years), 30 or Feb 31 (so php returns March 1, 2 or 3 respectively)
// Change the behavior of PHP over data-interval when the result of this function is Feb 29 (non-leap years), 30 or Feb 31 (so php returns March 1, 2 or 3 respectively)
if ($ruleforendofmonth == 1 && $duration_unit == 'm') {
$timeyear = (int) dol_print_date($time, '%Y');
$timemonth = (int) dol_print_date($time, '%m');
@@ -970,7 +973,7 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
// Geneva fast in Switzerland
}
}
//print "ferie=".$ferie."\n";
//print "ferie afterspe=".$ferie."\n";
// If we have to include Friday, Saturday and Sunday
if (!$ferie) {
@@ -990,7 +993,7 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
}
}
}
//print "ferie=".$ferie."\n";
//print "ferie afterincludexxxday=".$ferie."\n";
// We increase the counter of non working day
if ($ferie) {
@@ -998,8 +1001,9 @@ function num_public_holiday($timestampStart, $timestampEnd, $country_code = '',
}
// Increase number of days (on go up into loop)
//var_dump("before ".$jour.' '.$mois.' '.$annee.' '.$timestampStart);
$timestampStart = dol_time_plus_duree($timestampStart, 1, 'd');
//var_dump($jour.' '.$mois.' '.$annee.' '.$timestampStart);
//var_dump("after ".$jour.' '.$mois.' '.$annee.' '.$timestampStart);
$i++;
}
@@ -1335,7 +1339,9 @@ function num_open_day($timestampStart, $timestampEnd, $inhour = 0, $lastday = 0,
if ($timestampStart < $timestampEnd) {
// --- 1. Calculate Gross Working Days ---
// Gross working days = total days in range - non-working days (weekends & public holidays).
$nbOpenDay = num_between_day($timestampStart, $timestampEnd, $lastday) - num_public_holiday($timestampStart, $timestampEnd, $country_code, $lastday);
$a = num_between_day($timestampStart, $timestampEnd, $lastday);
$b = num_public_holiday($timestampStart, $timestampEnd, $country_code, $lastday);
$nbOpenDay = $a - $b;
// --- 2. Apply Contextual Half-Day Deductions ---
$halfday = (int) $halfday; // Ensure $halfday is an integer for reliable comparisons.

View File

@@ -3887,22 +3887,27 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs =
} else {
// Date is a timestamps
if ($time < 100000000000) { // Protection against bad date values
$timetouse = $time + $offsettz + $offsetdst; // TODO We could be able to disable use of offsettz and offsetdst to use only offsettzstring.
$dtts = new DateTime();
if ($to_gmt) {
$tzo = new DateTimeZone('UTC'); // when to_gmt is true, base for offsettz and offsetdst (so timetouse) is UTC
$dtts->setTimezone($tzo); // important: must be before the setTimestamp
$dtts->setTimestamp((int) $time);
} else {
$timetouse = (int) $time + $offsettz + $offsetdst; // TODO We could be able to disable use of offsettz and offsetdst to use only offsettzstring.
$tzo = new DateTimeZone(date_default_timezone_get()); // when to_gmt is false, base for offsettz and offsetdst (so timetouse) is PHP server
$dtts->setTimestamp($timetouse); // TODO May be we can invert setTimestamp and setTimezone
$dtts->setTimezone($tzo);
}
$dtts = new DateTime();
$dtts->setTimestamp($timetouse);
$dtts->setTimezone($tzo);
$newformat = str_replace(
array('%Y', '%y', '%m', '%d', '%H', '%I', '%M', '%S', '%p', '%w', 'T', 'Z', '__a__', '__A__', '__b__', '__B__'),
array('Y', 'y', 'm', 'd', 'H', 'h', 'i', 's', 'A', 'w', '__£__', '__$__', '__{__', '__}__', '__[__', '__]__'),
$format
);
$ret = $dtts->format($newformat);
//var_dump($timetouse, $offsettz, $offsetdst, $tzo, $newformat, $ret);
$ret = str_replace(
array('__£__', '__$__', '__{__', '__}__', '__[__', '__]__'),
array('T', 'Z', '__a__', '__A__', '__b__', '__B__'),

View File

@@ -1415,7 +1415,7 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') {
print $form->textwithpicto($langs->trans('NbUseDaysCP'), $htmlhelp);
print '</td>';
print '<td>';
print num_open_day($object->date_debut_gmt, $object->date_fin_gmt, 0, 1, $object->halfday);
print num_open_day($object->date_debut_gmt, $object->date_fin_gmt, 0, 1, (int) $object->halfday);
print '</td>';
print '</tr>';

View File

@@ -102,12 +102,6 @@ class DateLibTest extends CommonClassTest
print __METHOD__." result=".$result."\n";
$this->assertEquals(3, $result);
/*
$result = num_between_day(1514332800, 1538265600, 0);
print __METHOD__." result=".$result."\n";
$this->assertEquals(277, $result);
*/
return $result;
}
@@ -192,6 +186,15 @@ class DateLibTest extends CommonClassTest
$langs = $this->savlangs;
$db = $this->savdb;
// Check for sunday/sunday with time changing - Sunday 25 october 2025 - Sunday 1 november 2025
$date1 = dol_mktime(0, 0, 0, 10, 26, 2025, 'gmt');
$date2 = dol_mktime(0, 0, 0, 11, 1, 2025, 'gmt');
$result = num_open_day($date1, $date2, 0, 1, 0, 'FR');
print __METHOD__." result ".$result."\n";
$this->assertEquals(5, $result, 'NumPublicHoliday for FR with date start before date change end inding after');
// With same hours - Tuesday/Wednesday jan 2013
$date1 = dol_mktime(0, 0, 0, 1, 1, 2013, 'gmt'); // tuesday
$date2 = dol_mktime(0, 0, 0, 1, 2, 2013, 'gmt'); // wednesday
@@ -422,10 +425,15 @@ class DateLibTest extends CommonClassTest
$outputlangs->setDefaultLang('fr_FR');
$outputlangs->load("main");
$result = dol_print_date(dol_time_plus_duree(dol_time_plus_duree(dol_time_plus_duree(0, 1, 'm'), 1, 'y'), 1, 'd'), 'dayhour', true, $outputlangs);
$result = dol_print_date(dol_time_plus_duree(dol_time_plus_duree(dol_time_plus_duree(0, 1, 'm'), 1, 'y'), 1, 'd'), 'dayhour', 'gmt', $outputlangs);
print __METHOD__." result=".$result."\n";
$this->assertEquals('02/02/1971 00:00', $result);
// Add 4 days on a date just before daylight change
$result = dol_print_date(dol_time_plus_duree(dol_mktime(0, 0, 0, 10, 24, 2025, 'gmt'), 4, 'd'), 'dayhour', 'gmt', $outputlangs);
print __METHOD__." result=".$result."\n";
$this->assertEquals('28/10/2025 00:00', $result);
return $result;
}