Dates and Time - The OOP Way

The Date/Time PHP extension is a set of classes that allow you to work with almost all of the date and time related tasks. It's been available since the release of PHP 5.2 and the extension introduced several new classes, all of which are mapped to real life scenarios:

  • A date or a time is represented by a DateTime object.
  • A timezone of the world is represented by a DateTimeZone object.
  • DateInterval objects represent an interval. For example, when we say two days from now on, the "two days" is the interval. The DateInterval object doesn't rely on a specific date or time.
  • DatePeriod objects represent a period between two dates.

Now don't let the last two tip you off, we'll be looking at real world usage of these two in a moment.


From date() to DateTime

Whenever we want to show a date we used date(), it's simple and it works. You just need to pass the date format you need. But it's a real pain to manipulate, a good example is formatting dates and times according to a custom timezone.

DateTime does more than just return a formatted date, but before we go any further, you need to initiate a new DateTime object which represents your date and or time. Then we can do all sorts of cool stuff with it. A new instance is created just like any other PHP class.

The constructor of DateTime accepts a string parameter which defaults to "now", the current time and date. To create an object for a specific date, you should pass the specific date and time to it. Formatting for the parameter is self explanatory in most cases. Below you can find a few different examples of constructing your DateTime object:

When PHP is having a hard time understanding the format, it will throw an exception. A full list of the available formatting can be found in in the documentation

If there is no formatting that matches your needs, you can specify your own format by using DateTime::createFromFormat

Now that we have a DateTime object in hand we can do whole bunch of stuff, rather easily.

Unix Timestamp

Modifying Date/Times

Note that when out-of-range values are set, PHP will modify the date accordingly. For example, $date->setDate(2013, 12, 35); will generate 2014-01-04, the same goes for time.


Working With Multiple Dates

Now that you're obsessed with DateTime, the next thing you know, your apps will be filled with DateTime objects. You'll start to love dates and times like never before. From now on, you'll be dealing with DateTime objects, not "strings" that you have to pass to the strtotime function when you need to do a little math.

Say for example that you need to compare two birthdays:

Another scenario might be comparing two dates. We can compare dates against one another like so:

The diff call returns a DateInterval object. If we dump out the return value:

These are public properties. You can generate some friendly output from a DateInterval object:

What's best about the DateInterval object is that you can apply the interval to another DateTime object:

Note: Modifications to DateTime, such as adding doesn't return new DateTime objects, it affects the original object. Always keep this in mind when passing around DateTime objects throughout your app. PHP 5.5 introduced a new class that returns new objects upon modification.

diff isn't the only place where you can generate a DateInterval object. Since it's a class, new objects can be initiated as usual:

The amount of years/months/days etc., are passed in as a string to the constructor. More information can be found in the constructor's documentation.


Working With Timezones

When creating new DateTime objects, the second argument of the constructor defines a timezone. If we skip this, a default timezone will be grabbed from the php.ini's date.timezone. You can modify this at runtime by calling date_default_timezone_set:

You can also change timezones on the fly. As you may have guessed, first we need a Timezone object.

You can define the timezone while creating your new DateTime object:

However, an important thing to note is that setTimezone modifies the original DateTime object. What we're basically asking is, "format this date, to this timezone" whenever we call the setTimezone method. Now on the other hand, in the last example where we pass the timezone into the DateTime constructor, we're saying, "the date I'm creating is in this timezone".

A list of valid timezones are available in the online documentation.


DatePeriods

I think the official manual provides the best explanation:

A date period allows iteration over a set of dates and times, recurring at regular intervals, over a given period.

DatePeriod allows us to generate a set of DateTimes using two days that we define between an interval. We pass a starting date, an interval and an ending date. On each interval a new DateTime object is created.

Let's say that we want to get all of Sheldon's birth dates, since his birth:

The result would be:

Now by default, the DatePeriod includes the starting date that we pass in. However, the fourth argument to the constructor allows us to skip the start date:

Let's see how many birthday parties Neo has had before Sheldon was born:


Extending

All of the classes that we've covered today can be extended to use with your own methods. One popular usage is extending the DateTime with a __toString method so that you can properly print out a DateTime object without calling format.


A Couple Usage Scenarios

  • One of my personal approaches to using DateTime objects, is when dealing with date/time columns in databases. All of the dates are stored as UTC timezone dates. The app code only works with DateTime objects, but before the end query is generated, all of the dates are formatted to UTC. This approach has allowed me to work with multiple timezone inputs easily.

    I can pass in a New York time object and completely forget about formatting it, before going to the database. I can easily switch between Unix timestamps and regular date-time formatting in my database at anytime, my app code doesn't care as long as it gets a DateTime object.

  • I've also used DateInterval to simplify subscription payment logic. Using DateInterval objects to define the time between the subscription has made things really easy. I just need to apply the interval to last payment date.

Do you have any good date/time usage examples? Share them in the comments.


Wrap Up

The date time extension has so much to offer, if you're on the bleeding edge, there are new classes and interfaces introduced since PHP 5.5. Be sure to checkout the manual. Thanks for reading.

Tags:

Comments

Related Articles