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.

$date = new DateTime();

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:

new DateTime('2013, March 24') //DateTime representing 2013, March 24
new DateTime('2013-03-24') //DateTime representing 2013, March 24
new DateTime('+2 days') //DateTime representing 2 days from now on.
new DateTime('tomorrow')

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

DateTime::createFromFormat('j-M-Y', '24-Mar-2013');

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

Unix Timestamp

$date->getTimestamp(); //returns a unix timestamp

Modifying Date/Times

$date->setDate(2013, 12, 30); //yyyy, mm, dd will set the the specified date
$date->setTime(12, 3, 20); //hh, mm, ss (optional) will modify the time
$date->modify('tomorrow'); //string based manipulation
$date->setTimestamp(1364798550); //modify using a unix timestamp

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:

$sheldon = new DateTime('May 20th, 1980');
$neo     = new DateTime('March 11th, 1962');
if ($sheldon > $neo)
    echo 'Sheldon is younger than neo';

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

$diff = $neo->diff($sheldon);

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

DateInterval Object
(
    [y] => 18
    [m] => 2
    [d] => 9
    [h] => 0
    [i] => 0
    [s] => 0
    [invert] => 0
    [days] => 6645
)

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

$diff->format('Neo is older by %Y years and %m months older'); //Neo is older by 18 years and 2 months

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

$neo->add($diff); //neo's birthday changed to sheldon's

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:

$new_diff = new DateInterval('P2Y');

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:

date_default_timezone_set('America/New_York');
new DateTime('today'); //datetime object is on New York time

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

$timezone = new DateTimeZone('America/New_York');
$sheldon->setTimezone($timezone); //sheldon's birthday now on to New York

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

$sheldon = new DateTime('May 20th, 1980', $timezone);

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:

//since birthdays occur every year, the interval is one year
$interval = new DateInterval('P1Y');
//third argument is the end date, new DateTime() == right now
$period   = new DatePeriod($sheldon, $interval, new DateTime());
foreach($period as $dt) {
    //DateTime objects
    echo $dt->format('Y-m-d - D'), "\n";   
}

The result would be:

1981-05-20 - Wed
1982-05-20 - Thu
1983-05-20 - Fri
1984-05-20 - Sun
1985-05-20 - Mon
1986-05-20 - Tue
...

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:

$period   = new DatePeriod($sheldon, $interval, new DateTime(), DatePeriod::EXCLUDE_START_DATE);

Extending

One popular usage is extending the DateTime with a __toString method so that you can properly print out a DateTime object without calling format.

Categories: PHP

0 thoughts on “PHP Date and Time functions – The OOP Way”

Leave a Reply

Your email address will not be published. Required fields are marked *

8 − 8 =

Related Posts

PHP

7 Super-Handy PHP Functions for Beginners

Have you ever taken a look at the list of functions available in PHP? I just counted 5025. Granted, it depends on what extensions you have enabled, but still: that’s one heap of functions! While Read more...