For example, when a country changes time, there are 2 possibilities:
1.- If it changes to an earlier time, for example, at 3 Am in Central Europe, the last Sunday in October at 3 Am becomes 2 Am, therefore, if there is a date that is 02:30 am, 2 Dates and Hours are possible, one before the Change, and one after the Change.
2.- In Central Europe the Last Sunday of March at 2 Am becomes 3 Am, therefore if someone puts a date/time like this: 03-31-2024 at 02:30 Am, that LOCAL time It is theoretically impossible, since between 2 and 3 there is no possibility of Local Time.
Is there any code that warns about this?
For example, I have this code in PHP, I pass it a time zone, and it does not warn me that this time, 02:30:00Am, is not officially possible, and I would like it to warn me about these conflicting hours:
(The code has an error in JulianDay, below I make a comment with the correction, it is a small error, the link is already corrected)
https://timezonespro.com/php/test4.php?tzname=Europe/Madrid
<?php
$timezoneStr = $_GET["tzname"];
echo "TimeZone = " . $timezoneStr;
$datetime = "2024-03-31 02:30:00";
print '<br>';
echo "Local = " . $datetime;
$given = new DateTime($datetime, new DateTimeZone($timezoneStr));
$given->setTimezone(new DateTimeZone("UTC"));
$output = $given->format("Y-m-d H:i:s");
print '<br>';
echo "UTC = " . $output;
$ano = substr($output, 0, 4);
$mes = substr($output, 5, 2);
$dia = substr($output, 8, 2);
$hor = substr($output, 11, 2);
$min = substr($output, 14, 2);
$sec = substr($output, 17, 2);
print '<br>';
echo "Year = " . $ano;
print '<br>';
echo "Month = " . $mes;
print '<br>';
echo "Day = " . $dia;
print '<br>';
echo "Hours = " . $hor;
print '<br>';
echo "Minutes = " . $min;
print '<br>';
echo "Seconds = " . $sec;
$meses = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
$mesStr = $meses[intval($mes) - 1];
print '<br>';
echo $dia . "-" . $mesStr . "-" . $ano . " a las " . $hor . ":" . $min . ":" . $sec;
$secondsInTime = intval($hor * 3600) + intval($min * 60) + intval($sec);
$secondsInTimeDec = $secondsInTime / 86400;
$jd = GregorianToJD($mes, $dia, $ano);
$jdDec = intval($jd) + $secondsInTimeDec;
print '<br>';
echo "JulianDay = " . $jdDec;
?>
A code that warns of conflicting times in time changes in a country.
DateTime already handles such cases:
$dt = new DateTime('2024-03-31 02:30:00', new DateTimeZone('Europe/Madrid'));
echo $dt->format('Y-m-d H:i:s'); // prints: 2024-03-31 03:30:00
Notice how the "impossible" 02:30 became 03:30 automatically.
There is no warning, but you can always compare the formatted Y-m-d H:i:s strings of the date with and without timezone info, if you need to check if that happened.
As lafor noted, PHPs DateTime handles this for you.
Add these lines after you create $given DateTime object:
if ($given->format('Y-m-d H:i:s') != $datetime) {
echo "WARNING: $datetime is impossible in $timezoneStr. Automatically adjusted to account for daylight savings time.";
}
<?php
$timezoneStr = $_GET["tzname"];
echo "TimeZone = " . $timezoneStr;
$datetime = "2024-03-31 02:30:00";
print '<br>';
echo "Local = " . $datetime;
$given = new DateTime($datetime, new DateTimeZone($timezoneStr));
// check if $given was adjusted for daylight savings in locale
if ($given->format('Y-m-d H:i:s') != $datetime) {
echo "WARNING: $datetime is impossible in $timezoneStr. Automatically adjusted to account for daylight savings time.";
}
$given->setTimezone(new DateTimeZone("UTC"));
$output = $given->format("Y-m-d H:i:s");
print '<br>';
echo "UTC = " . $output;
$ano = substr($output, 0, 4);
$mes = substr($output, 5, 2);
$dia = substr($output, 8, 2);
$hor = substr($output, 11, 2);
$min = substr($output, 14, 2);
$sec = substr($output, 17, 2);
print '<br>';
echo "Year = " . $ano;
print '<br>';
echo "Month = " . $mes;
print '<br>';
echo "Day = " . $dia;
print '<br>';
echo "Hours = " . $hor;
print '<br>';
echo "Minutes = " . $min;
print '<br>';
echo "Seconds = " . $sec;
$meses = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
$mesStr = $meses[intval($mes) - 1];
print '<br>';
echo $dia . "-" . $mesStr . "-" . $ano . " a las " . $hor . ":" . $min . ":" . $sec;
$secondsInTime = intval($hor * 3600) + intval($min * 60) + intval($sec);
$secondsInTimeDec = $secondsInTime / 86400;
$jd = GregorianToJD($mes, $dia, $ano);
$jdDec = intval($jd) + $secondsInTimeDec;
print '<br>';
echo "JulianDay = " . $jdDec;
?>
BTW - you may want to check out Carbon. I have nothing to do with it's development, but I've used it whenever possible since I discovered a few years ago. It has saved me countless headaches.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With