# date_diff broken?

- Thread: https://externals.io/message/53350
- Original archive: https://news-web.php.net/php.internals/53350
- Started by Stas Malyshev on 2011-06-16T23:51:09+00:00
- Messages: 12
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #53350 — Stas Malyshev — 2011-06-16T23:51:09+00:00

URL: https://externals.io/message/53350#53350

Hi!

I've been looking into various tests and discovered something strange in 
date_diff. Example code:

<?php
$start = new DateTime('2010-10-04 02:18:48 EDT');
$end   = new DateTime('2010-11-06 18:38:28 EDT');
$int = $start->diff($end);
var_dump($start);

As a result of this I'm getting this:

object(DateTime)#1 (3) {
   ["date"]=>
   string(19) "2010-10-04 06:18:48"
   ["timezone_type"]=>
   int(2)
   ["timezone"]=>
   string(3) "EDT"
}

As you can see, the date in $start changed, even though it shouldn't 
happen. Looks like it's because of timelib_diff() which has this:

     timelib_apply_localtime(one, 0);
     timelib_apply_localtime(two, 0);

which converts times in diff arguments to localtime. It then does:

     timelib_apply_localtime(one, 1);
     timelib_apply_localtime(two, 1);

which is supposed to convert them back, but in fact it does not, since 
first conversion seems to have killed TZ information. I'd propose to fix 
it by making time_diff operate on copies of one and two instead of real 
structures, but maybe somebody has a better idea?
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #53351 — Richard Quadling — 2011-06-17T09:18:26+00:00

URL: https://externals.io/message/53350#53351 · In reply to: #53350

> Hi!
>
> I've been looking into various tests and discovered something strange in
> date_diff. Example code:
>
> <?php
> $start = new DateTime('2010-10-04 02:18:48 EDT');
> $end   = new DateTime('2010-11-06 18:38:28 EDT');
> $int = $start->diff($end);
> var_dump($start);
>
> As a result of this I'm getting this:
>
> object(DateTime)#1 (3) {
>  ["date"]=>
>  string(19) "2010-10-04 06:18:48"
>  ["timezone_type"]=>
>  int(2)
>  ["timezone"]=>
>  string(3) "EDT"
> }
>
> As you can see, the date in $start changed, even though it shouldn't happen.
> Looks like it's because of timelib_diff() which has this:
>
>    timelib_apply_localtime(one, 0);
>    timelib_apply_localtime(two, 0);
>
> which converts times in diff arguments to localtime. It then does:
>
>    timelib_apply_localtime(one, 1);
>    timelib_apply_localtime(two, 1);
>
> which is supposed to convert them back, but in fact it does not, since first
> conversion seems to have killed TZ information. I'd propose to fix it by
> making time_diff operate on copies of one and two instead of real
> structures, but maybe somebody has a better idea?


Just ran Stas' script against a lot of 5.3's.

V5.3.0alpha2 :   string(19) "2010-10-04 06:18:48"
V5.3.0alpha3 :   string(19) "2010-10-04 06:18:48"
V5.3.0beta1 :   string(19) "2010-10-04 06:18:48"
V5.3.0RC2 :   string(19) "2010-10-04 06:18:48"
V5.3.0RC3 :   string(19) "2010-10-04 06:18:48"
V5.3.0RC4 :   string(19) "2010-10-04 06:18:48"
V5.3.0 :   string(19) "2010-10-04 06:18:48"
V5.3.1RC1 :   string(19) "2010-10-04 06:18:48"
V5.3.1RC2 :   string(19) "2010-10-04 06:18:48"
V5.3.1RC3 :   string(19) "2010-10-04 06:18:48"
V5.3.1RC4 :   string(19) "2010-10-04 06:18:48"
V5.3.1 :   string(19) "2010-10-04 06:18:48"
V5.3.2RC1 :   string(19) "2010-10-04 06:18:48"
V5.3.2RC2 :   string(19) "2010-10-04 06:18:48"
V5.3.2RC3 :   string(19) "2010-10-04 06:18:48"
V5.3.2 :   string(19) "2010-10-04 06:18:48"
V5.3.3RC1 :   string(19) "2010-10-04 06:18:48"
V5.3.3RC2 :   string(19) "2010-10-04 06:18:48"
V5.3.3RC3 :   string(19) "2010-10-04 06:18:48"
V5.3.3 :   string(19) "2010-10-04 06:18:48"
V5.3.4RC1 :   string(19) "2010-10-04 06:18:48"
V5.3.4RC2 :   string(19) "2010-10-04 06:18:48"
V5.3.4 :   string(19) "2010-10-04 06:18:48"
V5.3.5 :   string(19) "2010-10-04 06:18:48"
V5.3.6RC1 :   string(19) "2010-10-04 06:18:48"
V5.3.6RC2 :   string(19) "2010-10-04 06:18:48"
V5.3.6RC3 :   string(19) "2010-10-04 06:18:48"
V5.3.6 :   string(19) "2010-10-04 06:18:48"


Even though the behaviour is wrong, it is consistent.

There are no user notes commenting on this issue in the documentation.

Can't check the bug base at the moment due to it being down.

If either of the dates use a TLA timezone (EDT, PST, GMT), rather than
the long name (Europe/London, Indian/Kerguelen,
America/Kentucky/Louisville), then that date is altered.

Richard.

-- 
Richard Quadling
Twitter : EE : Zend : PHPDoc
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY : bit.ly/lFnVea

---

## #53352 — Derick Rethans — 2011-06-17T11:40:34+00:00

URL: https://externals.io/message/53350#53352 · In reply to: #53351

> 
> > […]

Well, we need to check on why the TZ information got killed actually. As 
that's not supposed to happen. I see why this happens in the library, 
let me think of a way on how to fix this in a clean way.

cheers,
Derick

-- 
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug

---

## #53353 — Stas Malyshev — 2011-06-17T15:02:01+00:00

URL: https://externals.io/message/53350#53353 · In reply to: #53351

Hi!

> If either of the dates use a TLA timezone (EDT, PST, GMT), rather than
> the long name (Europe/London, Indian/Kerguelen,
> America/Kentucky/Louisville), then that date is altered.

Yes, this seems to be because TLA ones rely on ->z and ->dst which get 
reset in timelib_unixtime2gmt() while other one relies on tzinfo which 
is kept intact.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #53354 — Derick Rethans — 2011-06-17T15:13:51+00:00

URL: https://externals.io/message/53350#53354 · In reply to: #53353

> > […]
> 
> Yes, this seems to be because TLA ones rely on ->z and ->dst which get 
> reset in timelib_unixtime2gmt() while other one relies on tzinfo which 
> is kept intact.

Yup. I'm fixing it right now.

cheers,
Derick

-- 
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug

---

## #53355 — Derick Rethans — 2011-06-17T16:54:16+00:00

URL: https://externals.io/message/53350#53355 · In reply to: #53354

> 
> 
> > […]
> 
> Yup. I'm fixing it right now.

Done... I had to do it by making a backup for now. It should be looked 
at again though, and I've added that to my (long) todo list.

cheers,
Derick

-- 
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug

---

## #53358 — Hannes Magnusson — 2011-06-17T17:11:53+00:00

URL: https://externals.io/message/53350#53358 · In reply to: #53355

> 
>
> > […]
>
> Done... I had to do it by making a backup for now. It should be looked
> at again though, and I've added that to my (long) todo list.

Does it mean that all the tests Daniel added should work now?
http://news.php.net/php.cvs/65174

-Hannes

---

## #53362 — Stas Malyshev — 2011-06-17T18:43:09+00:00

URL: https://externals.io/message/53350#53362 · In reply to: #53358

Hi!

> Does it mean that all the tests Daniel added should work now?
> http://news.php.net/php.cvs/65174

Unfortunately, not yet. There seems to be another bug there, diff works 
fine now but add gives wrong result.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #53363 — Stas Malyshev — 2011-06-17T19:06:36+00:00

URL: https://externals.io/message/53350#53363 · In reply to: #53358

Hi!

> Does it mean that all the tests Daniel added should work now?
> http://news.php.net/php.cvs/65174

Looks like ts->date conversion is broken on TLA timezones. Try:

<?php
$t   = new DateTime('2010-11-06 18:38:28 EDT');  // prev, zt2
$ts = $t->format('U');
var_dump($ts);
$t->setTimestamp($ts);
var_dump($t);

That produces:

object(DateTime)#1 (3) {
   ["date"]=>
   string(19) "2010-11-06 17:38:28"
   ["timezone_type"]=>
   int(2)
   ["timezone"]=>
   string(3) "EDT"
}

Which obviously is not what it should be. Looks like 
timelib_unixtime2gmt() or timelib_update_from_sse() has some bug that 
breaks it...

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #53367 — Daniel Convissor — 2011-06-18T01:05:09+00:00

URL: https://externals.io/message/53350#53367 · In reply to: #53350

Hi Stas:

> $start = new DateTime('2010-10-04 02:18:48 EDT');
> $end   = new DateTime('2010-11-06 18:38:28 EDT');
> $int = $start->diff($end);
... snip ...
> As you can see, the date in $start changed, even though it shouldn't
> happen.

Funny you should mention that now.  I ran into the same exact issue as
I was reworking the DateTime unit tests yesterday.  I came up with a
.phpt for it, and another one for a similar problem with DateTime::add(),
though I was waiting to commit them until bugs.php.net was back up so
I could get bug numbers for them.

I just updated my checkout and the diff() problem is fixed, but the
add() one still exists.  bug.add.zone2.phpt has now been committed.  In
brief, calling add() on DateTime objects with zone type2 pushes back the
time by an hour.  For example:

<?php
$interval = new DateInterval('PT2H1M');
$date2 = new DateTime('2010-10-04 02:18:48 EDT');
echo $interval->format('Add %h hours %i minutes') . "\n";
$date2->add($interval);
echo 'Zone Type 2: ' . $date2->format('Y-m-d H:i:s T') . "\n";
?>

Output:
Zone Type 2: 2010-10-04 03:19:48 EDT

Expected:
Zone Type 2: 2010-10-04 04:19:48 EDT

Thanks,

--Dan

-- 
 T H E   A N A L Y S I S   A N D   S O L U T I O N S   C O M P A N Y
            data intensive web and database programming
                http://www.AnalysisAndSolutions.com/
 4015 7th Ave #4, Brooklyn NY 11232  v: 718-854-0335 f: 718-854-0409

---

## #53368 — Daniel Convissor — 2011-06-18T01:13:08+00:00

URL: https://externals.io/message/53350#53368 · In reply to: #53358

Hi Hannes:


> 
> Does it mean that all the tests Daniel added should work now?
> http://news.php.net/php.cvs/65174

Alas, no.  There are other bugs in the bed.

--Dan

-- 
 T H E   A N A L Y S I S   A N D   S O L U T I O N S   C O M P A N Y
            data intensive web and database programming
                http://www.AnalysisAndSolutions.com/
 4015 7th Ave #4, Brooklyn NY 11232  v: 718-854-0335 f: 718-854-0409

---

## #53369 — Derick Rethans — 2011-06-18T09:41:20+00:00

URL: https://externals.io/message/53350#53369 · In reply to: #53363

> Hi!
> 
> > […]
> 
> Looks like ts->date conversion is broken on TLA timezones. Try:
> 
> <?php
> $t   = new DateTime('2010-11-06 18:38:28 EDT');  // prev, zt2
> $ts = $t->format('U');
> var_dump($ts);
> $t->setTimestamp($ts);
> var_dump($t);
> 
> That produces:
> 
> object(DateTime)#1 (3) {
>   ["date"]=>
>   string(19) "2010-11-06 17:38:28"
>   ["timezone_type"]=>
>   int(2)
>   ["timezone"]=>
>   string(3) "EDT"
> }
> 
> Which obviously is not what it should be. Looks like timelib_unixtime2gmt() or
> timelib_update_from_sse() has some bug that breaks it...

Yes, I know. It's probably because of the "dst" flag. I did see that 
yesterday, but didn't have the time to fix it yet, or look at it.

cheers,
Derick

-- 
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug
