Bug #80748 [Nab]: DateInterval wrongly counts DateTime->diff days

From: Date: Mon, 15 Feb 2021 23:14:07 +0000
Subject: Bug #80748 [Nab]: DateInterval wrongly counts DateTime->diff days
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-232174@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=80748&edit=1 ID: 80748 Updated by: requinix@php.net Reported by: palansher at outlook dot com Summary: DateInterval wrongly counts DateTime->diff days Status: Not a bug Type: Bug Package: Date/time related Operating System: ubuntu 18.04 PHP Version: Irrelevant Block user comment: N Private report: N New Comment: > it seems that the reason can be the "leap seconds" 1. There have been 37 leap seconds. I don't see how that can turn into 43 seconds. 2. The first leap second was in 1972. If you diff 1900 to 1970 then the difference still occurs with 25604/25605 days. It is not leap seconds. > in the last code example I set UTC timezone, not Moscow. Actually no. In your code where you use setTimezone, what you do is create a DateTime *according to the default timezone* and then modify the date to use the new timezone. If you want PHP to parse a date string according to a certain timezone then you have to specify that timezone at the time of parsing: with createFromFormat. https://3v4l.org/mWIjk Note that 3v4l's default timezone is Europe/Amsterdam, which used unusual UTC offsets through the 1930s. (Of course UTC didn't actually exist until the 1960s, so accusing Amsterdam of doing something weird according to a standard that hadn't been developed yet would be unfair.) Previous Comments: ------------------------------------------------------------------------ [2021-02-15 13:21:12] palansher at outlook dot com @requinix@php.net >Before 1917, Moscow was GMT+02:30:17. Those 17 seconds account for the odd >behavior >around:43 seconds when you use diffs between <1917 and >1917. Thank you! But I doubt it, because: 1) in the last code example I set UTC timezone, not Moscow. 2) How timezone affects the number of seconds in a year? Such a number is always the same in any timezone, depending on the particular year of course... 3) it seems that the reason can be the "leap seconds" https://en.wikipedia.org/wiki/Leap_second. And DT->diff doesn't pay attention to it. ------------------------------------------------------------------------ [2021-02-14 21:28:36] requinix@php.net Before 1917, Moscow was GMT+02:30:17. Those 17 seconds account for the odd behavior around :43 seconds when you use diffs between <1917 and >1917. ------------------------------------------------------------------------ [2021-02-14 17:17:36] palansher at outlook dot com Found another incorrect behaviour: $beforDate=DateTime::createFromFormat('Y-m-d G:i:s', '1900-01-01 00:00:00'); $beforDate->setTimezone(new DateTimeZone('UTC')); $afterDate=DateTime::createFromFormat('Y-m-d G:i:s', '2021-02-08 00:00:00'); $afterDate->setTimezone(new DateTimeZone('UTC')); $dtInterval = $beforDate->diff($afterDate); $daysPassed = $dtInterval->days; echo "1. days passed: $daysPassed" . PHP_EOL; $afterDate=DateTime::createFromFormat('Y-m-d G:i:s', '2021-02-08 00:50:00'); $afterDate->setTimezone(new DateTimeZone('UTC')); $dtInterval = $beforDate->diff($afterDate); $daysPassed = $dtInterval->days; echo "1. days passed if 50 minutes added to target date: $daysPassed" . PHP_EOL; Have output: days passed: 44232 days passed if 50 minutes added to target date: 44233 https://3v4l.org/49Dv0 ------------------------------------------------------------------------ [2021-02-14 14:50:15] palansher at outlook dot com requinix@php.net, you are right. The date_default_timezone_set('Europe/Moscow'); was set. But!! a year has the same number of days in any timezone. How timezone can affect the total days number? ------------------------------------------------------------------------ [2021-02-14 14:43:21] palansher at outlook dot com Just realized: This error appears if default timezone set, like date_default_timezone_set('Europe/Moscow'); But timezone must not affect the result. corrected code: date_default_timezone_set('Europe/Moscow'); $beforDate=DateTime::createFromFormat('Y-m-d G:i:s', '1900-01-01 00:00:00'); $afterDate=DateTime::createFromFormat('Y-m-d G:i:s', '2021-02-08 00:00:42'); $dtInterval = $beforDate->diff($afterDate); $daysPassed = $dtInterval->days; echo "1. days passed if target date have 42 seconds from midnight: $daysPassed" . PHP_EOL; $afterDate=DateTime::createFromFormat('Y-m-d G:i:s', '2021-02-08 00:00:43'); $dtInterval = $beforDate->diff($afterDate); $daysPassed = $dtInterval->days; echo "2. days passed if target date have 43 seconds from midnight: $daysPassed" . PHP_EOL; result: 1. days passed if target date have 42 seconds from midnight: 44232 2. days passed if target date have 43 seconds from midnight: 44233 ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=80748 -- Edit this bug report at https://bugs.php.net/bug.php?id=80748&edit=1

« previous php.bugs (#232174) next »