Working With Date And Time In Object Oriented Way

pomosda Slawek Lukasiewicz

Date and time manipulation in PHP is mostly connected with functions like: date, time or strtotime. They can be sufficient, but if we want to deal with dates like with objects we can use DateTime class. DateTime class is not only straightforward wrapper for standard functions, it has a lot of additional features for example timezones.

Date creation

public DateTime::__construct() ([ string $time = "now" [, DateTimeZone $timezone = NULL ]] )

During DateTime object creation we can set time and timezone. Time can be represented as one of supported formats

Date and time formats examples:

<?php
$date = new DateTime('2014-08-07 10:20:30');
print $date->format('d-m-Y H:i');
# 07-08-2014 10-20
print PHP_EOL;
 
$date = new DateTime('@223311122');
print $date->format('d-m-Y H:i');
# 28-01-1977 14-52
print PHP_EOL;

$date = new DateTime('9/24/72 12:20');
print $date->format('d-m-Y H:i');
# 24-09-1972 12-20
print PHP_EOL;

Notice: When using timestamp notation (@TIMESTAMP) timezone is ignored If we dont set timezone, the current timezone will be use.

Format date

Date is formatted by format method. It takes one parameter, format, which is format accepted by date function. Examples can be found above.

Date Comparison

We can compare DateTime objects with PHP comparison operators.
<?php

$dateA = new DateTime('2014-07-05');
$dateB = new DateTime('2014-07-07');
var_dump($dateA > $dateB);
# false
var_dump($dateA < $dateB);
# true

Altering date

DateTime object is mutable, it means that we can change date or time after creation. We can change date or time with setDate(), setTime() or setTimestamp() methods.
<?php
$date = new DateTime();
$date->setDate(2013, 11, 12);
$date->setTime(15, 10);
print $date->format('d-m-Y H:i');
#12-11-2013 15:10

Another possibility for altering date are sub and add methods, for respectively subtracting and adding date interval to our object. These methods takesDateInterval object as argument. According to documentation, DateInterval is:

Representation of date interval. A date interval stores either a fixed amount of time (in years, months, days, hours etc) or a relative time string in the format that DateTimes constructor supports. Example of using 2 days interval.

<?php

$date = new DateTime('2014-10-10');
$date->add(new DateInterval('P2D'));
print $date->format('d-m-Y');
#12-10-2013

print PHP_EOL;
 
$date = new DateTime('2014-10-10');
$date->sub(new DateInterval('P2D'));
print $date->format('d-m-Y');
#08-10-2013

More information about creating DateInterval object can be found here.DateInterval has also static method createFromDateString, which can create DateInterval object from relative parts of date string, as show below.

$dateInterval = DateInterval::createFromDateString('2 days');

We can also increment or decrement DateTime object using modify method.

<?php

$date = new DateTime('2014-10-10');
$date->modify('+1day');
print $date->format('d-m-Y');
#11-10-2013

Modify accepts strtotime format.

Notice: Sometimes modify can behave unintuitive. Derick Rethans wrote article about one such case.

Above methods return $this, so they can be used for method chaining.

<?php
$date = new DateTime();
$date->setDate(2013, 11, 12)->setTime(15, 10);
print $date->format('d-m-Y H:i');
#12-11-2013 15:10

Calculating difference between two DateTime objects

This is one of my favorite features in DateTime class. Using diff method we can calculate difference between two DateTime objects. Diff method returns DateInterval object.

<?php

$dateA = new DateTime('2014-10-10');
$dateB = new DateTime('2014-10-12');
 
$interval = $dateA->diff($dateB);
print $interval->format('days: %R %d');
#days: +2

$interval = $dateB->diff($dateA);
print $interval->format('days: %R %d');
#days: -2

Diff method has also second optional parameter, absolute when true is passed difference is return as absolute.

<?php

$dateA = new DateTime('2014-10-10');
$dateB = new DateTime('2014-10-12');
 
$interval = $dateB->diff($dateA);
print $interval->format('days: %R %d');
#days: -2

print PHP_EOL;
 
$interval = $dateB->diff($dateA, true);
print $interval->format('days: %R %d');
#days: +2

Iterating through date period

Another interesting class is DatePeriod, which can be used for iterating through some period of time. We can set start date (DateTime), interval for iterating (DateInterval), and optionally end date (DateTime). It can be really useful.

<?php

$dateStart = new DateTime('2014-10-10 10:00');
$dateEnd = new DateTime('2014-10-10 14:00');
$periodInterval = new DateInterval('PT1H');
 
$datePeriod = new DatePeriod($dateStart, $periodInterval, $dateEnd);
 
foreach ($datePeriod as $hourPeriod) {
	print $hourPeriod->format('d-m-Y H:i');
	print PHP_EOL;
}
# 10-10-2014 10:00
# 10-10-2014 11:00
# 10-10-2014 12:00
# 10-10-2014 13:00

DatePeriod has more types of constructors and can be used in completely different way.

<?php

$date1 = new DateTime(); 
$eightynine_days_ago = new DateInterval( "P89D" ); 
$eightynine_days_ago->invert = 1; //Make it negative. 
$date1->add( $eightynine_days_ago ); 

and then $date1 is now 89 days in the past.

NOTE : This DateInterval Class

<?php
// Built in with PHP
DateInterval {
/* Properties */
public integer $y ; // years
public integer $m ; // months
public integer $d ; // days
public integer $h ; // hours
public integer $i ; // minutes
public integer $s ; // seconds
public integer $invert ; 
public mixed $days ;
/* Methods */
public __construct ( string $interval_spec )
public static DateInterval createFromDateString ( string $time )
public string format ( string $format )
}

days

If the DateInterval object was created by DateTime::diff(), then this is the total number of days between the start and end dates. Otherwise, days will be FALSE.

Parameters

interval_spec

An interval specification.

The format starts with the letter P, for "period." Each duration period is represented by an integer value followed by a period designator. If the duration contains time elements, that portion of the specification is preceded by the letter T. Here are some simple examples.

Two days is P2D.
Two seconds is PT2S.
Six years and five minutes isP6YT5M.

Note:

The unit types must be entered from the largest scale unit on the left to the smallest scale unit on the right. So years before months, months before days, days before minutes, etc.

Thus one year and four days must be represented as P1Y4D, not P4D1Y.
The specification can also be represented as a date time. A sample of one year and four days would beP0001-00-04T00:00:00. But the values in this format can not exceed a given period's roll-over-point (e.g. 25hours is invalid).

  • 05 Sep 2014
  • By Slawek Lukasiewicz
  • PHP-5
  • 766 Read