Issues

ZF-2071: Zend_Date Constructor should respect timezone offsets in ISO 8601 date strings

Issue Type: New Feature Created: 2007-10-15T10:45:49.000+0000 Last Updated: 2008-03-21T16:25:31.000+0000 Status: Resolved Fix version(s): - 1.5.0 (17/Mar/08)

Reporter: Adam Jensen (jazzslider) Assignee: Thomas Weidner (thomas) Tags: - Zend_Date

Related issues: Attachments:

Description

Currently the Zend_Date constructor ignores timezone offsets specified in ISO 8601 date strings. For example:

<pre class="highlight">
date_default_timezone_set('America/Chicago');

$stringInDefaultTimezone = '2007-10-15T10:32:00-05:00';
$stringInCustomTimezone  = '2007-10-15T10:32:00+09:00';

$dateInDefaultTimezone = new Zend_Date($stringInDefaultTimezone, Zend_Date::ISO_8601);
$dateInCustomTimezone  = new Zend_Date($stringInCustomTimezone, Zend_Date::ISO_8601);

echo $dateInDefaultTimezone->get(Zend_Date::TIMESTAMP) . PHP_EOL;
echo $dateInCustomTimezone->get(Zend_Date::TIMESTAMP) . PHP_EOL;

The above code, given Zend_Date 1.0.2, produces identical timestamps for both date objects, even though the original strings referred to two different moments in time. The only way to produce the correct timestamps given the current functionality of Zend_Date is to set the timezone offset prior to setting the rest of the date, like so:

<pre class="highlight">
$dateInCustomTimezone = new Zend_Date();
$dateInCustomTimezone->set('+09:00', Zend_Date::GMT_DIFF_SEP);
$dateInCustomTimezone->set($stringInCustomTimezone, Zend_Date::ISO_8601);

This is much less convenient to the developer than simply specifying the date string in the constructor, and becomes particularly difficult when the developer is trying to process a dynamic collection of ISO 8601 dates in a variety of valid formats from a variety of timezones. Without knowing the timezone offset in advance, the developer will have to extract it from the string using regular expressions, which is an extra complexity many developers could do without.

It would be much more convenient to the developer if the constructor simply respected the timezone offset provided in the date string itself. Beyond that, it would be much more intuitive, as developers specifying timezone offsets in their date strings are probably expecting it to "just work"; I know that was my experience :)

Thanks for reading!

Comments

Posted by Adam Jensen (jazzslider) on 2007-10-15T11:21:25.000+0000

Aligned equal signs in code example for better readability.

Posted by Thomas Weidner (thomas) on 2008-02-03T05:03:09.000+0000

Integrated with SVN-7768

Timezone settings are now used and set as internal timezone if given. Also an additional method getTimezoneFromString() has been added.

Posted by Lode Blomme (lode) on 2008-02-10T16:56:05.000+0000

I ran into this problem today using Zend Framework 1.0.3. So I tried it with the code from SVN trunk, but I'm not satisfied with the behavior. I'm using a PostgreSQL database with timestamps with timezone in it. Those have to be displayed on a website to people in different timezones (they choose their timezone in a config panel).

<pre class="highlight">
date_default_timezone_set('Europe/Brussels');
$date = new Zend_Date('2008-02-10 10:00:00+00', Zend_Date::ISO_8601);
echo $date;

The result is : 10 feb 2008 10:00:00

While I expected it to be : 10 feb 2008 11:00:00 Since Brussels is GMT+1.

Posted by Thomas Weidner (thomas) on 2008-02-11T01:35:38.000+0000

Why should the timezone be +01 ? You set the timezone within your ISO String to +00 which is equal to GMT.

If you do not set any timezone than the timezone from default will be used... as the command says... "date_DEFAULT_timezone"... default if no timezone can be detected.

This is the same behaviour as if you would have done

<pre class="highlight">
date_default_timezone_set('Europe/Brussels');
$date = new Zend_Date('2008-02-10 10:00:00', Zend_Date::ISO_8601);
echo $date; // note the set timezone Brussels here
$date->setTimezone('+00:00');
echo $date; // oops... timezone changed !!

You can't really say that this is unexpected behaviour... if you set a timezone within your inputstring then it will be used... if you suppress the timezone then the timezone will be detected.

So you have 2 ways: You can eigther suppress the timezone before creating the date object... or if you are not able to change your input then you have to do some date-maths.

Posted by Lode Blomme (lode) on 2008-02-11T04:01:34.000+0000

Sorry, my mistake.

So if I want to display a certain date in a different timezone than it was created in, I do :

<pre class="highlight">
$date = new Zend_Date('2008-02-10 10:00:00+00', Zend_Date::ISO_8601);
// $date->setTimezone('+01:00'); is rejected with message 'timezone_open() [<a href="function.timezone-open">function.timezone-open</a>]: Unknown or bad timezone (+01:00)' in ...\Zend\Date\DateObject.php:1016
$date->setTimezone('Europe/Brussels');
echo $date;

That is indeed the behavior to expect.

But then I think I noticed a bug :

<pre class="highlight">
date_default_timezone_set('Europe/Brussels');
$date = new Zend_Date('2008-02-10 10:00:00+00', Zend_Date::ISO_8601);
$date->setTimezone('Europe/Brussels');
echo $date->get(Zend_Date::ISO_8601);

Outputs : 2008-02-10T10:00:00+01:00 Instead of : 2008-02-10T11:00:00+01:00

I think this is because in Zend_Date_DateObject on line 1009 the old timezone is fetched with :

<pre class="highlight">
$oldzone = @date_default_timezone_get();

Where it gets 'Europe/Brussels' as old timezone, so it doesn't make any changes.

It does work when I do :

<pre class="highlight">
date_default_timezone_set('Europe/London');
$date = new Zend_Date('2008-02-10 10:00:00+00', Zend_Date::ISO_8601);
$date->setTimezone('Europe/Brussels');
echo $date->get(Zend_Date::ISO_8601);

But that would mean I have to detect the timezone from the input string myself, and set the date_default_timezone accordingly.

Posted by Thomas Weidner (thomas) on 2008-02-11T05:58:17.000+0000

You should use the latest trunk version... Also to mention +00 is not a timezone.

When you are having problems with the latest version from trunk please give * PHP Version * OS * ZF SVN Version * Reproducable code

Otherwise we are not able to reproduce the behaviour. Within SVN7910 I found no problems with the code you gave for reproduction.

Btw: The codelines you are referring to have nothing to do with the recognition of the timezone.

Posted by Lode Blomme (lode) on 2008-02-11T13:42:05.000+0000

PHP Version 5.2.0 in Zend Studio 5.5.0 Windows XP SP2 ZF SVN 7919

Code :

<pre class="highlight">
date_default_timezone_set('Europe/Brussels');
$date = new Zend_Date('2008-02-10 10:00:00+00', Zend_Date::ISO_8601);
$date->setTimezone('Europe/Brussels');
echo $date->get(Zend_Date::ISO_8601);

Doesn't work correct here. But I was indeed wrong about the reason. I can make it work by using :

<pre class="highlight">
as input instead of :

PostgreSQL doesn't give the minutes in the offset. If I may believe Wikipedia (http://en.wikipedia.org/wiki/ISO_8601) it doesn't have to.

Have you found an issue?

See the Overview section for more details.

Copyright

© 2006-2016 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.

Contacts