php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76057 For DateTime the properties 'timezone' and 'timezone_type' are not set on init
Submitted: 2018-03-05 21:04 UTC Modified: 2018-03-11 12:27 UTC
From: projectcleverweb at gmail dot com Assigned:
Status: Duplicate Package: Date/time related
PHP Version: 7.2.3 OS: Linux
Private report: No CVE-ID: None
 [2018-03-05 21:04 UTC] projectcleverweb at gmail dot com
Description:
------------
In short, these to properties are not set when the class is instantiated, but do become set when the class is serialized OR when the property list is requested (such as via get_object_vars()).

You can see the conditions when timezone_type will be set on this page by just searching in the browser for "timezone_type"

https://github.com/php/php-src/blob/ef255c9f0f2c2ad1ea224ed215edb00f5bc205bd/ext/date/php_date.c#L2269

This issue is occurring on PHP 5.6 and later (shown in the test script URL)

Test script:
---------------
https://3v4l.org/ZhQX9

--- OR ---

$test = new DateTime('2018-03-05 00:00:00', new DateTimeZone('UTC'));
var_dump($test->timezone); // Notice: Undefined property: DateTime::$timezone
get_object_vars($test);
var_dump($test->timezone); // string(3) "UTC"

Expected result:
----------------
string(3) "UTC"
string(3) "UTC"

Actual result:
--------------
Notice: Undefined property: DateTime::$timezone in /in/BQD1t on line 5
NULL
string(3) "UTC"

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-03-08 14:49 UTC] jhdxr@php.net
This behavior (get timezone via property) is not expected, you should use `getTimezone()` to retrieve timezone.
 [2018-03-08 18:34 UTC] projectcleverweb at gmail dot com
Ok then, if they are not intended to be used they both should simply be protected or private properties; however, in this case how are you supposed to access $timezone_type?

If you are writing your own serialization method (or in my case an extension of DateTime) you would have to make an exception for DateTime because even though it has a __set_state() method, that method requires the value of $timezone_type.

See: https://3v4l.org/Klvo3

Ideally DateTimeZone (and possibly DateTime) would have a getTimezoneType() method.
 [2018-03-11 12:18 UTC] heiglandreas@php.net
You can get the timezone-type as follows:

$timezone = $date->getTimezone();
$location = $timezone->getLocation();
$type = 2;
if (false !== $location) {
    $type = '3';
}
if (preg_match('/[\+\-]\d{2}:\d{2}/', $timezone->getName())) {
    $type = '1';
}

As a timezone-object sets the timezone type depending on the given value you don't need to set the timezone-type explicitly. 

And when you are extending the DateTime-Class (hopefully DateTimeImmutable but that's a different story) you are free to add a method getTimezoneType using the above code.

The internal properties of the DateTime-Objects are initialized after a var_dump which is a known thing and can not be fixed as easily as it seems. You should under no circumstances depend on them but use the available API.
 [2018-03-11 12:27 UTC] heiglandreas@php.net
-Status: Open +Status: Duplicate
 [2018-03-11 12:27 UTC] heiglandreas@php.net
Have a look at https://3v4l.org/TPWi1
 [2018-03-13 22:34 UTC] projectcleverweb at gmail dot com
Now I could be mistaken, but I don't see anywhere in the official documentation on how $timezone_type can be determined. Which means this code is relying on the undocumented inner-workings of PHP.

To be clear, I am thankful to you that you have provided a workaround, but that solution would be considered janky at best.

I have no doubt that it works, but because it relies on the undocumented inner-workings of PHP (Which as we all know can and will be updated without notice or being documented on the official pages of PHP.net) it could break at any time with no warning.

Which is why I was hoping to have a method added to DateTimeZone. Honestly, it's kind of surprising to hear these values aren't already stored as properties. I mean I would imagine you have to determine them anyway to initialize the class or change the timezone, so it would simply be a matter of updating the properties when that happens.

Furthermore, this data *appears* to already be stored in C as a property (see "dateobj->time->zone_type" in the source). However, I don't actually know how to program in C so it is very possible I am just misunderstanding this.

---

For now, I have opted for calling get_object_vars($this) after the following methods are called: __construct, modify, setTimezone to ensure that $timezone and $timezone_type are always set correctly.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 15:01:29 2024 UTC