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