36

I use Doctrine2 on Postgres. In one table I have got two different date types: birthdate:date and created_at:datetimetz. Both become DateTime object but with different timezone_type. Here are listings:

created_at datetimetz:

DateTime Object
(
    [date] => 2013-04-18 11:54:34
    [timezone_type] => 1
    [timezone] => +02:00
)

birthdate date:

DateTime Object
(
    [date] => 1970-01-01 00:00:00
    [timezone_type] => 3
    [timezone] => Europe/Berlin
)

I need to format my objects in the same way. Both should have timezone_type=3.

How can I achieve that?

vascowhite
  • 18,120
  • 9
  • 61
  • 77
lilly
  • 661
  • 1
  • 7
  • 17
  • 1
    `date_timezone_set ( DateTime $object , DateTimeZone $timezone )` – DevZer0 Jul 17 '13 at 08:37
  • The code you propose only sets the timezone. In listings above, timezones are the same, but they are presented differently. – lilly Jul 17 '13 at 14:26
  • If you use `$mytime->setTimezone(new DateTimezone('Europe/Berlin'))` (or whatever) on each one, the result will be that they are presented the same way. – Jerry Dec 06 '17 at 22:29

2 Answers2

89

Timezones can be one of three different types in DateTime objects:

  • Type 1; A UTC offset, such as in new DateTime("17 July 2013 -0300");
  • Type 2; A timezone abbreviation, such as in new DateTime("17 July 2013 GMT");
  • Type 3: A timezone identifier, such as in new DateTime( "17 July 2013", new DateTimeZone("Europe/London"));

Only DateTime objects with type 3 timezones attached will allow for DST correctly.

In order to always have type 3 you will need to store the timezone in your database as accepted identifiers from this list and apply it to your DateTime object on instantiation.

vascowhite
  • 18,120
  • 9
  • 61
  • 77
  • 1
    Well.. I do store this type 3 timezone in database. What appears to be a problem is that Doctrine2 returns those differet timezone types (even after I explicitly pass timezone as \DateTimeZone("Europe/London")). I don't think I have easy access to modify Doctrine2 behaviour thus I already decided to use simple timestamps with the consumer class to do datetime formatting. Or maybe I've left something unnoticed? Have you ever worked on DateTime objects from Doctrine2+Postgres and made it work? – lilly Jul 18 '13 at 12:06
  • Sorry, I've never used Doctrine, I'm not a fan of ORM's, but I have used the [Doctrine DBAL](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/index.html) and never come across your issue as I retain control over my data and how it is manipulated. – vascowhite Jul 18 '13 at 14:51
  • 3
    Having the same problem with a different ORM, I found out, that `$new=new DateTime(); $new->setTimestamp($old->getTimestamp());` does the trick, albeit very ugly. Including this in setters eases the pain. – Eugen Rieck Jul 10 '14 at 20:50
  • Using type 1 also allows a correct DST, as DST is already included in it. You don't need to apply it. That is why it's the stantard ISO 8601... – Softlion Jun 08 '19 at 08:04
  • 1
    @Softlion if I add 6 months to the DateTime in type 1 it will be 1 hour out as it won’t know about the DST transition that takes place sometime around October. The type 3 will account for the transition correctly. – vascowhite Jun 08 '19 at 21:33
  • 1
    @vascowhite Is this mapping listed in the documentation anywhere? – GPHemsley Mar 22 '20 at 20:45
  • 1
    @GPHemsley I don’t think so. I found it out by testing and reading source code. I vaguely remember reading a comment somewhere that confirmed my findings, but it was a long time ago and I can’t recall where. – vascowhite Mar 23 '20 at 21:07
1

I know this is an ancient post, but since Doctrine was mentioned, I feel the need to share what I've recently experienced regarding this issue.

@vascowhite is correct, but regarding Doctrine (at least on my configuration) dates sent to the server (e.g. to save) via HTTP are converted timezone type 2. Doctrine handles them properly and saves the date correctly, but it does not convert the timezone type.

If you are performing a "save and and return fresh values" type operation, note that Doctrine will use the cached value (with timezone_type 2). This becomes important when you are expecting timezone_type 3 as you would normally get during a page reload. We have a custom date converter JS class that expects timezone_type 3 and it was unable to convert it. Admittedly, the date converter should account for this, but also one should be aware that the timezone type will be the last loaded value in Doctrine. Clearing Doctrine's cache after saving will force the data to reload with timezone_type 3.

alwayslearning
  • 268
  • 2
  • 9