Working With PHP's Date and Time Classes
Ever since version 5.2, PHP has provided the amazing
DateTime
class that makes it a lot easier to work with dates and times. This article will provide an overview of the class and how it can be used and show some of the other classes that are related to the DateTime
class.
Creating
The easiest way to work with the DateTime
class is to just create a new instance of it. Without any parameters the DateTime
class uses the date and time that the class was initialized.
Command
$date = new DateTime();
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2018-12-11 11:34:54"
As a quick aside, the format()
function converts the date and time into a string representation of the object. I’m using the {four digit year}-{two digit month}-{two digit day} {two digit 24 hour time hour}:{two digit minute}:{two digit seconds} format throughout this article as it’s my preferred date time format because it’s sorted largest time interval to smallest.
You can also create a DateTime
object for a specific date and time:
Command
$date = new DateTime("2018-12-01 00:00:00");
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2018-12-01 00:00:00"
PHP also has a long list of relative date formats so you can generate a DateTime
using more readable formats like the following:
Command
$date = new DateTime("first day of December");
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2018-12-01 00:00:00"
Formating Dates
I’ve already jumped the gun on this but the format()
function allow you to convert a DateTime
object into a string. This is helpful if you want to display the date to the user or save the value to a database/file. The format()
function uses the same formatting characters as the date()
function so you can see all the options on the documentation page for the date()
function but it also includes a couple built in formats like RSS:
Command
$date = new DateTime("2018-12-01 00:00:00");
var_dump($date->format(DateTime::RSS));
Output
string(31) "Sat, 01 Dec 2018 00:00:00 +0000"
The complete list of these formats can be found at http://php.net/manual/en/class.datetime.php.
I tend to use the MySQL format a lot:
Command
$date = new DateTime("2018-12-01 00:00:00");
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2018-12-01 00:00:00"
It’s also helpful to have the “normal” format that people in the US use:
Command
$date = new DateTime("2018-12-01 00:00:00");
var_dump($date->format("m/d/y"));
Output
string(8) "12/01/18"
Or if you’re in the rest of the world:
Command
$date = new DateTime("2018-12-01 00:00:00");
var_dump($date->format("d/m/y"));
Output
string(8) "01/12/18"
Creating From Formatted Dates
Invariably, you’re going to need to take an input from your user and work with it. The worst case for a date is getting something like 11/12/08. Now is this November 12th, 2008 or December 11th, 2008? If we just enter this string into a new DateTime
class we’ll end up with November 12th.
Command
$date = new DateTime("11/12/08 08:00:00");
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2008-11-12 08:00:00"
Using the createFromFormat()
function we can specify the format of the date:
Command
$date = DateTime::createFromFormat("d/m/y h:i:s", "11/12/08 08:00:00");
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2008-12-11 08:00:00"
Adding and Subtracting Time
Up until this point most of you might have been thinking “So what, the date()
function can do most of that”. Prepare to have your mind blown.
The true power of the DateTime
class, IMHO, is how easy it lets you manipulate time after you’ve created it. For example, if you want to add a month to the current date you can use the modify()
function to do so:
Command
$date = new DateTime("2018-12-01 00:00:00");
$date->modify("+1 month");
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2019-01-01 00:00:00"
Or you can add a year and a month:
Command
$date = new DateTime("2018-12-01 00:00:00");
$date->modify("+1 year +1 month");
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2020-01-01 00:00:00"
Or subtract a year and add a month:
Command
$date = new DateTime("2018-12-01 00:00:00");
$date->modify("-1 year +1 month");
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2018-01-01 00:00:00"
The DateTime
class also provides an add()
and subtract()
function which still allow you to modify the DateTime
but in a format that’s a little harder to read. The function requires you to create a new DateInterval
class and pass it a string formatted with how you want it changed. I personally recommend the modify()
function because of how easy it is to read but below is an example that adds 1 Month (‘1M’) to the date.
Command
$date = new DateTime("2018-12-01 00:00:00");
$date->add(new DateInterval('P1M'));
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2019-01-01 00:00:00"
And here’s another that adds 1 Year (‘1Y’) and 1 Month (‘1M’):
Command
$date = new DateTime("2018-12-01 00:00:00");
$date->add(new DateInterval('P1Y1M'));
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2020-01-01 00:00:00"
Comparing Two Dates
If you need to determine the difference between two dates you can use the diff()
function to create a DateInterval
object which will then allow you to see the difference between the two dates
Command
$date1 = new DateTime("2018-12-01 00:00:00");
$date2 = new DateTime("2020-01-25 01:01:01");
$diff = $date1->diff($date2);
echo "years -> {$diff->y}", PHP_EOL;
echo "months -> {$diff->m}", PHP_EOL;
echo "days -> {$diff->d}", PHP_EOL;
echo "hours -> {$diff->h}", PHP_EOL;
echo "minutes -> {$diff->i}", PHP_EOL;
echo "seconds -> {$diff->s}", PHP_EOL;
echo "total days -> {$diff->days}", PHP_EOL;
Output
years -> 1
months -> 1
days -> 24
hours -> 1
minutes -> 1
seconds -> 1
total days -> 420
It also has a format()
function that will allow you to create a formatted version of the same information. It’s important to note it use the percent sign to show where the variables need to go. It also adds a “%R” option which will tell you if there’s a positive or negative difference between the two dates.
Command
$date1 = new DateTime("2018-12-01 00:00:00");
$date2 = new DateTime("2020-01-25 01:01:01");
$diff = $date1->diff($date2);
var_dump($diff->format("%y years %m months %d days %H:%i:%s and %R%a total days"));
Output
string(51) "1 years 1 months 24 days 01:1:1 and +420 total days"
Timezones
I have written before about what I learned while writing a timezone aware website but using the DateTime
class makes it a lot easier to shift between timezones. One of the things I’ve excluded up to this point is the fact that the DateTime
constructor has a second optional parameter that determines the timezone that the DateTime
exists within. Then you can call setTimeZone()
to shift that date and time into the timezone you’re interested in. This process is significantly easier that working with raw time()
numbers to get it into the correct timezone.
Command
$date = new DateTime("2018-12-01 00:00:00", new DateTimeZone("UTC"));
$date->setTimezone(new DateTimeZone("America/Detroit"));
var_dump($date->format("Y-m-d H:i:s"));
Output
string(19) "2018-11-30 19:00:00"
Iterating Over A Date Range
If you need to work on every date between two dates you can use the DatePeriod
class to loop through every date inside that range. For example, if you need to do something to every date in the month of December 2018 you can do the following.
$startDate = new DateTime("2018-12-01");
$endDate = new DateTime("2019-01-01");
$interval = new DateInterval("P1D");
$period = new DatePeriod($startDate, $interval, $endDate);
foreach ($period as $currentDate) {
echo $currentDate->format("m/d"), PHP_EOL;
}
Output
12/01
12/02
12/03
12/04
... output removed to reduce space ...
12/29
12/30
12/31
This example just outputs the date but you could do any kind of calculation inside the foreach
loop.
Conclusion
This is just an overview of the power of PHP’s date and time classes. If we missed something or this has been helpful to you let us know in the comments.
Scott Keck-Warren
Scott is the Director of Technology at WeCare Connect where he strives to provide solutions for his customers needs. He's the father of two and can be found most weekends working on projects around the house with his loving partner.
Top Posts
- Working With Soft Deletes in Laravel (By Example)
- Fixing CMake was unable to find a build program corresponding to "Unix Makefiles"
- Upgrading to Laravel 8.x
- Get The Count of the Number of Users in an AD Group
- Multiple Vagrant VMs in One Vagrantfile
- Fixing the "this is larger than GitHub's recommended maximum file size of 50.00 MB" error
- Changing the Directory Vagrant Stores the VMs In
- Accepting Android SDK Licenses From The OSX Command Line
- Fixing the 'Target class [config] does not exist' Error
- Using Rectangle to Manage MacOS Windows