Mirko Pagliai
Mirko Pagliai

Reputation: 1240

CakePHP: FrozenTime from database without timezone

I'm on "Europe/Rome":

debug(new \Cake\I18n\Time());

Output:

object(Cake\I18n\Time) {

    'time' => '2016-03-23T14:18:17+01:00',
    'timezone' => 'Europe/Rome',
    'fixedNowTime' => false

}

If I save a post (for example), the datatime is handled properly.
The problem occurs when I retrieve data. This post has been just saved:

debug($post->created);

Output:

object(Cake\I18n\FrozenTime) {

    'time' => '2016-03-23T14:14:45+00:00',
    'timezone' => 'UTC',
    'fixedNowTime' => false

}

The datetime is correct, but the timezone of course not.

Now if I do something like this:

debug($post->created > new \Cake\I18n\Time());

the result will obviously be TRUE and not FALSE (as it should be). I conclude that this happens because, in comparison phase, it obviously uses the same timezone.

Where am I doing wrong? Thanks.


EDIT My bootstrap.php

date_default_timezone_set('UTC');

Instead, my php.ini (I think it's not relevant):

date.timezone = Europe/Rome

So I have to think that the value of $post->created is correct.
But now... why new \Cake\I18n\Time() uses the correct timezone (which is not set) and why the post is saved with the correct timezone?

Upvotes: 0

Views: 1447

Answers (1)

ndm
ndm

Reputation: 60473

I would kinda doubt that new \Cake\I18n\Time() will use the timezone set in your INI after date_default_timezone_set() has been used, as the latter should win over the former. Maybe there's a version specific behavior/bug where this doesn't work as expected, not sure, you'll have to debug your environment to figure what's going on there.

That being said, when data is being read, the ORM casts it to PHP datatypes. The date/time type classes responsible for this are using cloned date/time class instances instead of creating new ones, and that base instance is created when the type instance is first built and/or when the mutability is being set, which usually happens at bootstrapping time when Type::build() is invoked.

If you'd then for example change the timezone at a later point, new \Cake\I18n\Time based instances would use the newly set timezone, but the date/time type would still use the instance that was created with the original timezone at bootstrapping time.

tl;dr

Set the proper timezone via date_default_timezone_set() in your bootstrap, and if you need to change the timezone at a later point, then you'll have to make sure that a new base type instance for cloning is being set, which could for example be done by setting the mutability again, like

Type::build('time')->useImmutable();

This feels kinda workaroundish though, you may want to open a ticket over at GitHub and report this behavior.

Upvotes: 1

Related Questions