Every developer has to deal with it at some point in their career. It is always there. It is persistent, relentlessly ticking away and eating productivity. It keeps track of when things happen, and can cause you pain when trying to work with it. What is it? Time (and time zones in particular).
We’ve all been there. We have our killer app, released to the public, then people start reporting strange dates. “What do you mean? This works perfectly,” you say to yourself. Until you realize that you, and everyone on your QA team that tested the application, are in the same time zone. When someone from another time zone uses your app – when that fateful day arrives, you best be compensating for it. Otherwise your data will get sketchy pretty fast.
The Default Time Zone
Fortunately, you always have a baseline to work from: the server’s time zone. Some would argue that you should use UTC, but as long as something is the standard that everything is converted to, you have a known value to work from.
Every time you create a new date without giving it a time zone, it will be in the server’s time zone. From there we can convert it to whatever we need for the user. Likewise, if we store the dates in a database based on the server’s time zone, it will be easy to correlate events because everything has been normalized.
Working with Dates as Objects
In PHP, one can work with dates as either an Object or old procedural code. In the first example, we are going to cover Objects.
Thanks to object oriented design (OOP), converting a Date object is straightforward. Consider the following code:
echo 'America/Los_Angeles:<br>';
$date = new DateTime('2015-01-01', new DateTimeZone('America/Los_Angeles'));
echo $date->format('Y-m-d H:i:sP') . "<br><br>";
This will create a DateTime object in the Pacific time zone (America/Los_Angeles). Now, let’s say that we want to convert this date to the Eastern time zone.
echo 'America/New_York:<br>';
$date->setTimezone(new DateTimeZone('America/New_York'));
echo $date->format('Y-m-d H:i:sP') . "<br><br>";
The second example takes the DateTime object we created in the first, and simply alters the time zone by calling setTimezone, and passing in the new time zone we want to use (America/New_York). Easy right?
Procedural
The procedural example works much the same, but uses function aliases to access all the same methods as the Object Oriented example:
echo 'Object Oriented<br>';
$date = date_create('2015-01-01', timezone_open('America/Los_Angeles'));
echo date_format($date, 'Y-m-d H:i:sP') . '<br><br>';
echo 'America/New_York:<br>';
date_timezone_set($date, timezone_open('America/New_York'));
echo date_format($date, 'Y-m-d H:i:sP') . '<br><br>';
As you can see, things are a bit more hodge-podge and not as easy as calling a function on an object, but it still accomplishes the same goal.
Gotchas
The key to doing date conversion is knowing your source. I repeat: KNOW YOUR SOURCE. All the DateTime functions in the world won’t help if you have no idea what time zone the source data is in. When working with web applications, if you are accepting any dates from the client side, they will most likely be in the client’s time zone. This is something that needs to be determined before you can normalize the data. Some applications take care of this by having user settings that explicitly say what the time zone is. Others rely solely on the back-end for dates.
The bottom line is, once you’ve normalized your inputs, time zone conversion is easy. Have I mentioned you need to know your inputs?