PhpRiot
News Archive
PhpRiot Newsletter
Your Email Address:

More information

Dates and Times

Note: This article was originally published at Planet PHP on 6 December 2011.
Planet PHP

Having dealt with a lot of dates and timesa-aand the calculations between thema-a recently, I thought it might be a good idea to write down some of the issues I've encountered.

The truth is, dates and times are hard! There are many different rules that make dealing with dates and times non-trivial. Often, people make mistakes, causing loss of information and general confusion.

Deciding on a format

One of the observations I've made is that nearly every system out there lacks a standard for passing around date and time values.

The most common formats are MySQL (YYYY-MM-DD HH:MM:SS), timestamps (what time() produces), and DateTime.

There are benefits to all of these, but it's important that you need to decide on one. Make sure any date/time that enters your app through any means is converted immediately to this standard. This includes, for example, the result of a MySQL query, data from $_POST, or the response from a web service.

Make sure this enters your coding standards document.

Using DateTime

Deciding on a standard date format and following it religiously is much more important than which standard you choose. If you have a choice, though, I recommend the DateTime object.

The standard inclusion of the DateTime object in PHP is one of the best things that has happened to PHP in recent times. It replaces all the functionality of the existing date functions, and there's really no need to use anything else.

One of the benefits you'll get is that you can type hint it like every other class, which means it will be easier to spot bugs, and it's self-documenting. Also, you can pretty much treat it like a timestamp:

$dt1 = new DateTime('yesterday'); $dt2 = new DateTime('next wednesday'); if ($dt1 $dt2) { echo "Hell froze over!\n" };

As you can see, because DateTime is actually a PHP extension, it gets the privilege of overloading operators such as . Plus, it handles timezones.

DateTime also makes it easy to do relative calculations. If you want to increase a date by exactly one month, how many seconds you need to add the start date depends on the month of the year, wether it's a leap year or not, which timezone you're in, and whether a leap second has been scheduled that year. It's easier let DateTime do it:

$dt = new DateTime('December 25th, 2011'); $dt-modify('+1 month');

Using time zones

I've noticed that a lot of people simply use their local timezone. This is a bad idea, because it's not always immediately clear, it's ambiguous, and it can cause obscure bugs. It will also not always be possible to convert to different timezones if your app ends up going international.

The reason it's ambiguous is simple. Every year, in most European countries, the end of Daylight savings time is the last Sunday in October. On that day, every second between 02:00 and 03:00 occurs twice. Thus, one ambiguity when using time zones is that these seconds that occur twice are not unique, so you can no longer determine if a time is referring to before the switchover or after. This can cause bugs when doing date comparisons. Adding a second could mean the same thing as subtracting 59 minutes and 59 seconds.

The start of DST is similar, which is why you might see gaps in log files and whatnot.

So, make sure that when you deploy your app, the server as well as PHP are configured to use UTC or GMT. UTC time is time zone independent, so every second of the year is, well, unique.

You'll have to get into the habit of converting times to your local time zone in your presentation layer. On the plus side, it will be easy to support other time zones in the future.

You can always accurately convert from UTC to your local time zone, but you cannot always accurately convert from your local time zone to UTC. (It is a lossy conversion.)

// Changing time zones $dt = new DateTime('2011-10-07 12:00:00'); $dt-setTimeZone(new DateTimeZone('Europe/Lisbon')); echo $dt-format(DateTime::RFC2822);

Storing dates and times in MySQL

There are three possible data types you can use to store dates and times in MySQL. You can use DATETIME, TIMESTAMP, or INT (for storing a timestamp).

DATETIME is a popular choice, and in most cases, it's fine. Just remember that DATETIME is 8 bytes, whereas a TIMESTAMP

Truncated by Planet PHP, read more at the original (another 2941 bytes)