Bug #80748 [Nab]: DateInterval wrongly counts DateTime->diff days
| From: | requinix@php.net | 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