UTC Time Confusion with PHP

With the coming of spring and just like the Daffodils erupting from the soil, a whole new selection of bugs appear in your code due to the clocks going forward one hour.

My matrix display project needs to refresh from the dataset once in a while and yesterday with the clocks going forward from GMT to BST a bug caused the refresh time to be set behind or at the same time as the current time in UTC resulting in the matrix display continually sending update requests to the server. As you are probably aware, GMT and UTC are the same time, while BST is one hour ahead.

The Problem

Skip to the end for the fix if you are impatient.

With the failure as described above, I quickly found the problem in my PHP code, the DateTime class automatically sets the timezone region to that used in the application, in my case Europe/London, any conversions made are set relative to that timezone. The matrix display uses a Unix Timestamp for all time calculations, I could have written the code on the server side to use Unix Timestamps, but it turns out that I didn’t and now I need to convert between date strings, date objects and timestamp integers.

In the MySQL database I store the date as a DATETIME but with no timezone information, like so:

I then go to retrieve this date from the database, and convert it back to a PHP datetime object, and in this case display it:

And the output for this would be:

What you can see here is that while the datetime object is correct the timezone is set to Europe/London so when this is converted to a unix timestamp with $nextUpdate->getTimestamp(); an hour is deducted to convert it to UTC.

My first attempt at fixing this (now omitting the database query for clarity):

made things worse:

While the timezone is now correct the datetime object has also lost an hour.

The Fix

Turns out all that is needed is to set the timezone when the datetime object is created:

to give this resulting output:

So setting the timezone after creating the datetime object modifies the time, giving the setTimeZone() function a bit of a misleading name.

Links and Sources