php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77571 DateTime's diff DateInterval incorrect in timezones from UTC+01:00 to UTC+12:00
Submitted: 2019-02-05 15:26 UTC Modified: 2019-02-12 18:40 UTC
Votes:5
Avg. Score:4.0 ± 0.9
Reproduced:4 of 4 (100.0%)
Same Version:3 (75.0%)
Same OS:2 (50.0%)
From: techouse at gmail dot com Assigned:
Status: Open Package: Date/time related
PHP Version: 7.3.1, 7.2.10 OS: macOS 10.14.3, Ubuntu 18.04
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2019-02-05 15:26 UTC] techouse at gmail dot com
Description:
------------
Yesterday I observed a weird DateInterval bug where adding 5 weeks would always equal 35 days but the difference in months and days would not be correct.

After some digging I figured out it was related to timezones and only affected timezones ranging from Europe/London eastward all the way to Pacific/Auckland, however as soon as I used Pacific/Honolulu the issue was gone.

Test findings

All the tests in tests/Timezones/America and tests/Timezones/Atlantic pass. Another weird thing is that Europe/London passes all tests where it does not adhere to daylight savings time (UTC+01:00).

From this I draw a conclusion that all timezones that are greater than UTC+00:00 fail because of this additional time.

All the tests and findings can be found in my GitHub repo https://github.com/techouse/php-date-interval-timezone-bug

Test script:
---------------
https://github.com/techouse/php-date-interval-timezone-bug

Expected result:
----------------
A correct DateInterval.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-02-06 08:20 UTC] techouse at gmail dot com
-Summary: DateInterval timezone bug +Summary: DateInterval reports incorrect interval when when a UTC+01:00 or greater is used -PHP Version: 7.3.1 +PHP Version: 7.3.1, 7.2.10
 [2019-02-06 08:20 UTC] techouse at gmail dot com
Updated the summary to be more descriptive and added another tested PHP version.
 [2019-02-06 08:22 UTC] techouse at gmail dot com
-Summary: DateInterval reports incorrect interval when when a UTC+01:00 or greater is used +Summary: DateInterval has incorrect interval using timezones from UTC+01:00 to UTC+12:00
 [2019-02-06 08:22 UTC] techouse at gmail dot com
Better summary
 [2019-02-06 08:55 UTC] techouse at gmail dot com
Might be related to https://bugs.php.net/bug.php?id=52480
 [2019-02-07 01:19 UTC] a at b dot c dot de
May also be related to bug #76374
 [2019-02-07 08:44 UTC] techouse at gmail dot com
I simply copied this test https://github.com/php/php-src/blob/master/ext/date/tests/DateInterval_format.phpt and changed the timezone from UTC to Europe/Paris and the test fails.


--TEST--
DateInterval::format() with timezone, except %a
--DESCRIPTION--
%a is covered in a separate test.
Don't want an XFAIL here to cause confusion if a real bug comes up.
--CREDITS--
Daniel Convissor <danielc@php.net>
# TestFest 2010 BKTK
--SKIPIF--
<?php if (!method_exists('DateInterval', 'format')) die("skip: method doesn't exist"); ?>
--FILE--
<?php
//date_default_timezone_set('UTC');
date_default_timezone_set('Europe/Paris');

$date1 = new DateTime('2000-01-01 00:00:00');
$date2 = new DateTime('2001-03-04 04:05:06');

$interval = $date1->diff($date2);

echo $interval->format('Y=%Y') . "\n";
echo $interval->format('M=%M') . "\n";
echo $interval->format('D=%D') . "\n";
echo $interval->format('H=%H') . "\n";
echo $interval->format('I=%I') . "\n";
echo $interval->format('S=%S') . "\n";
echo $interval->format('R=%R') . "\n";

echo $interval->format('y=%y') . "\n";
echo $interval->format('m=%m') . "\n";
echo $interval->format('d=%d') . "\n";
echo $interval->format('h=%h') . "\n";
echo $interval->format('i=%i') . "\n";
echo $interval->format('s=%s') . "\n";
echo $interval->format('r=%r') . "\n";

echo "\n";

$interval = $date2->diff($date1);

echo $interval->format('inverted R=%R') . "\n";
echo $interval->format('inverted r=%r') . "\n";

echo "\n";

echo $interval->format('%=%%') . "\n";

// Invalid valid format character does not raise warnings.
echo $interval->format('x=%x') . "\n";

?>
--EXPECT--
Y=01
M=02
D=03
H=04
I=05
S=06
R=+
y=1
m=2
d=3
h=4
i=5
s=6
r=

inverted R=-
inverted r=-

%=%
x=%x
 [2019-02-12 14:56 UTC] techouse at gmail dot com
-Summary: DateInterval has incorrect interval using timezones from UTC+01:00 to UTC+12:00 +Summary: DateTime's diff DateInterval incorrect in timezones from UTC+01:00 to UTC+12:00
 [2019-02-12 14:56 UTC] techouse at gmail dot com
Changed the title to have more meaning
 [2019-02-12 14:57 UTC] techouse at gmail dot com
My work colleague found out that this feature worked correctly in PHP 5.3.0, 5.3.1 and 5.3.2, however in 5.3.3 we can already observe this bug in action. Check for yourself https://3v4l.org/cupQV
 [2019-02-12 18:40 UTC] cmb@php.net
It seems to me that boils down to the question: “how many days
does a month have?”  Answer: it depends.  For instance, May has 31
days, so 31 days + 4 days = 35 days.  Correct.

If you revert the ::diff()[1], you see that April has 30 days, so
30 days + 5 days = 35 days.  Correct again.

[1] <https://3v4l.org/gocOc>
 [2019-02-12 20:24 UTC] techouse at gmail dot com
Yes, but that makes a negative diff which is not what I want. Basically in order to get a correct date I would have to subtract a negative interval instead of adding a positive one?! How crazy of an idea is that?? 

https://3v4l.org/2MNE3
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue Sep 24 08:01:27 2019 UTC