Have you ever wanted to work with PHP’s DatePeriod
object. This object introduced in PHP 5.3.0 enables iterating over a set of dates and times (ie datepoints), recurring at regular intervals, over a given time range. In practice, on instantiation this object produces a Traversable
that generate DateTimeInterface
objects. This can be helpful, for instance, if you want to produce data reports at specific datepoints over a time range.
The easiest way to instantiate such object is to give the constructor a starting and an ending datepoints as well as the interval between each recurrence.
By default the ending datepoint is not returned and you can further exclude the starting datepoint by using the class constant DatePeriod::EXCLUDE_START_DATE
.
With the introduction of the DateTimeImmutable
object in PHP5.5, and a subsequent bug fix to DatePeriod
in PHP5.5.8, the object results became rather interesting. To sum it up, when iterating over a DatePeriod
, the datepoint returned is of the same instance as the starting datepoint. Let’s illustrate this by taking the first example and using a DateTimeImmutable
object instead as the starting datepoint.
Iterating the DatePeriod
will now return DateTimeImmutable
objects instead.
Now that we understand how the iteration works, we need to know how to get informations about an already instantiated DatePeriod
object ?
DatePeriod
exposes its properties using two distinct API that share a common trait, they are undocumented.
If you are on PHP5.6.5+ you should use the recommend API
If you are using an older version of PHP, you may use the fact that DatePeriod
exposes a copy of its internal state.
The latter API is buggy for different reasons:
- The datepoint value does not returns the instance expected. In the example we gave it a
DateTimeImmutable
object yet start returns aDateTime
object - The returned
DateInterval
object is in an invalid state and no usable. - No HHVM version supports this API.
What to take from this ?
- Always rely on the interface meaning if an object is said to return a
DateTimeInterface
do not try to use methods or property outside of the intended interface as the result may be unexpected. - Upgrade you PHP’s installation to the latest stable version when possible
Post Scriptum: If you want to further manipulate your time range in PHP, I would recommend the use of Period. This library, I maintain, is part of the PHP league. Period is composed of a single class that handles time range in a uniform and predicable way. The class which comes with many useful named constructors, compares and modifies time range easily by being an immutable value object just like the DateTimeImmutable
object.
League\Period is an open sourced project on Github, and is easily available using composer. You are, of course, welcome to contribute to the source code to improve it.
Ignace, thanks for pointing out the undocumented getter methods. They are now documented! [1] [2]
[1] The documentation commit: http://svn.php.net/viewvc/?view=revision&revision=339177
[2] DatePeriod manual page: http://php.net/dateperiod