Manipulation of dates and times in PHP with the DateTime native class

Following the article on the manipulation of dates in SQL, I realized that, in fact, the manipulation of date in php was not so simple and known as that. There are many functions on dates in PHP and I still find a lot of code that gets confused trying to calculate dates with mktime, manipulating timestamps.
While a very practical class exists: DateTime.
So it is she, and her companions, that I will present.

Introduction

Since PHP 5.5, there is 2 DateTime class, DateTime and DateTimeImmutable. They have a common interface, DateTimeInterface and their behaviour are quite similar. The only difference is that DateTimeImmutable, as the name suggests, can't be modified. So DateTimeImmutable will return a new object when DateTime will change the current object. In the article I will speak of DateTime and use mainly it in the examples, but I could use one or the other.

Initializing a date

To start any manipulation, you need a date. Nothing more simple, just instantiate the class DateTime to have the current date!

$date = new DateTime();

Be careful though, if no timezone is indicated in your php.ini file, you will have an error. In this case it will be necessary to specify it on the fly:

$date = new DateTime(null, new DateTimeZone('Europe/Paris'));

For a specific date, just put a string in place of null, several formats are allowed. But, for example, the value entered in a datetime field of a sql database works very well!

$date = new DateTime('2012-09-01 12:00:00");

You can also specify a relative date at this time:

$date = new DateTime("+ 2 days");
$date = new DateTime('next sunday");

Extracting a date

It's possible to extract every part of the dates, under almost every conceivable formats.
Here are some examples:

$date = new DateTime('2012-09-01 09:00:00', new DateTimeZone('Europe/Paris'));
echo $date->format('m-d-Y'); //01-09-2012
echo $date->format('g\hi'); //9h00
echo $date->format('F, \t\h\e jS'); //September, the 1st
echo $dateformat('\i\t \i\s \t\h\e NS \d\a\y \o\f \t\h\e \w\e\e\k.'); //it is the 6st day of the week.

Date manipulation

To modify a date, several possibilities are available to us.
We can directly modify our DateTime object:

$date = new DateTime('2012-09-01 09:00:00', new DateTimeZone('Europe/Paris'));
$date->modify("+ 2 days");
echo $date->format('m-d'); //03-09

But to be more precise (and more typed object), we can use the class DateInterval. To initiate it, the cleanest is to pass it in ISO8601 format.
Then add or subtract this interval to our date.

$date = new DateTimeImmutable('2012-09-01 09:00:00', new DateTimeZone('Europe/Paris'));
$interval = new DateInterval('P10D'); //10 days
 
$date2 = $date->add($interval);
echo $date2->format('Y-m-d'); //2012-09-11
 
$date3 = $date->sub($interval);
echo $date3->format('Y-m-d'); //2012-08-22

The DateInterval class is also used in the date comparison.
We can write very well:

var_dump($date2 > $date3) //true

And the diff function of the DateTime class will return the difference between the 2 dates in the form of an interval, which itself can be extracted in different formats.

$diff = $date2->diff($date3);
echo $diff->format('%R%d days'); //+20 days

List of dates

Let's say it's September 1st, and we want to list every Monday from today until the end of the month.

$begin = new DateTime('2012-09-01 09:00:00', new DateTimeZone('Europe/Paris')); 
$begin->modify('next monday');  
$interval = new DateInterval('P1W'); //one week interval
$end = clone $begin;
$end->modify('last day of this month');
$period = new DatePeriod($begin, $interval, $end);
foreach ($period as $date) {
   echo $date->format('l, F \t\h\e jS');
}
// Monday, September the 10st
// Monday, September the 17st
// Monday, September the 24st

That's not what I wanted, because I also wanted to have the first Monday of the month. Except we consider the first date of the period after a first application of the interval.
I can either start my period on the previous Monday:

$begin = new DateTime('2012-09-01 09:00:00', new DateTimeZone('Europe/Paris'));
$begin->modify('last monday');
$interval = new DateInterval('P1W');
$end = clone $begin;
$end->modify('last day of next month');
$period = new DatePeriod($begin, $interval, $end);
foreach ($period as $date) {
   echo $date->format('l, F \t\h\e jS');
}
// Monday, September the 3rd
// Monday, September the 10st
// Monday, September the 17st
// Monday, September the 24st

Either I can modify my interval by telling him to take the following Monday, but in this case you have to instantiate it from a string of characters.

$begin = new DateTime('2012-09-01 09:00:00', new DateTimeZone('Europe/Paris'));
$interval = DateInterval::createFromDateString('next monday');
$end = clone $begin;
$end->modify('last day of this month');
$period = new DatePeriod($begin, $interval, $end);
foreach ($period as $date) {
   echo $date->format('l, F \t\h\e jS');
}
// Monday, September the 3rd
// Monday, September the 10st
// Monday, September the 17st
// Monday, September the 24st

Conclusion

So, I hope you liked this article and made you want to play with these classes if you did not know them!

Add a comment