php[architect] logo

Want to check out an issue? Sign up to receive a special offer.

The PHP DateTime Class

Posted by on October 23, 2022

As a developer, you're going to run into situations where you need to perform some kind of operation on a date or time. You might need to see how far apart two dates are, add several days to the date, or convert a string sent to us by an end user into something we can work with.

As an inexperienced developer, I had not invented here syndrome for these kinds of problems all the time. I ended up spending a lot of time fixing bugs in my data handling logic instead of adding features to solve my user's problems.

As an experienced developer, I know I can reach for PHP's built-in date-time classes or one of the libraries built off of them.

In this article, we'll discuss how to use PHP's built-in DateTime classes to perform some basic operations on DateTime data.

Creating

The easiest way to work with a DateTime class is to just create a new instance of it. Without any parameters, the DateTime class uses the date and time at the moment that that class was initialized. As a quick aside, the format function converts the DateTime into a string representation of the object.

$date = new DateTime();
// output: string(19) "2022-10-09 18:39:16"
var_dump($date->format("Y-m-d H:i:s"));

You can also create a DateTime object for a specific date and time.

$date = new DateTime("2022-12-01 00:00:00");
// output: string(19) "2022-12-01 00:00:00"
var_dump($date->format("Y-m-d H:i:s"));

PHP also has a long list of relative date formats so you can generate a DateTime using more readable formats like the following.

$date = new DateTime("first day of december");
// output: string(19) "2022-12-01 00:00:00"
var_dump($date->format("Y-m-d H:i:s"));

Formatting Dates

I've already jumped the gun on this, but the format() function allows you to convert a DateTime object into a string. This is helpful if you want to display the date to a user or save the value to a database or a file.

There are a wide variety of formatting options that can be found in the online documentation, but it also includes a couple of built-in formats like RSS.

$date = new DateTime("2022-12-01 00:00:00");
// output: string(31) "Thu, 01 Dec 2022 00:00:00 +0000"
var_dump($date->format(DateTime::RSS));

The complete list of these formats can be found on the PHP website.

https://www.php.net/manual/en/datetime.format.php

Creating From Formatted Dates

Invariably, you're going to have to take input from your user to work with. The worst case for a date is getting something like "11/12/08". Now is this November 12, 2008, or December 11, 2008?

If we just enter this string into a new DateTime class, we'll end up with November 12th.

Using the createFromFormat() function, we can specify the format of that date.

$date = DateTime::createFromFormat(
    "d/m/y h:i:s",
    "11/12/08 08:00:00"
);
// output: string(19) “2008-12-11 08:00:00"
var_dump($date->format("Y-m-d H:i:s"));

Adding and Subtracting Time

Up until this point, most of you have been thinking, so what the date() function can do everything you just showed me. The true power of the DateTime class is how easily 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.

$date = new DateTime("2022-12-01 00:00:00");
$date->modify("+1 month");
// output: string(19) “2023-01-01 00:00:00"
var_dump($date->format("Y-m-d H:i:s"));

Or you can add a year and a month.

$date = new DateTime("2022-12-01 00:00:00");
$date->modify("+1 year +1 month");
// output: string(19) “2024-01-01 00:00:00"
var_dump($date->format("Y-m-d H:i:s"));

Or subtract a year and add a month.

$date = new DateTime("2022-12-01 00:00:00");
$date->modify("-1 year +1 month");
// output: string(19) “2022-01-01 00:00:00"
var_dump($date->format("Y-m-d H:i:s"));

The DateTime class also provides an add and subtract function, which still allows 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 exactly how you want to change.

$date = new DateTime("2022-12-01 00:00:00");
$date->add(new DateInterval('P1M'));
// output: string(19) “2023-01-01 00:00:00"
var_dump($date->format("Y-m-d H:i:s"));

I recommend the modify() function because of how easy it is to read, but this is an example of how you add a month to the date.

$date = new DateTime("2022-12-01 00:00:00");
$date->add(new DateInterval('P1M'));
// output: string(19) “2023-01-01 00:00:00"
var_dump($date->format("Y-m-d H:i:s"));

And here's another that adds a year and a month.

$date = new DateTime("2022-12-01 00:00:00");
$date->add(new DateInterval('P1Y1M'));
// output: string(19) “2024-01-01 00:00:00"
var_dump($date->format("Y-m-d H:i:s"));

Comparing Two Dates

If you need to determine the difference between two days, you can use the diff() function to create a DateInterval object, which will then allow you to see the difference between those two dates.

$date1 = new DateTime("2022-12-01 00:00:00");
$date2 = new DateTime(“2024-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;

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 uses the percent sign to show where the variables need to go, and it also adds a %R option, which will tell you if there's a positive or negative difference between two dates.

$date1 = new DateTime("2022-12-01 00:00:00");
$date2 = new DateTime("2024-01-25 01:01:01");
$diff = $date1->diff($date2);
// output: string(51) "1 years 1 months 24 days 01:1:1 and +420 total days"
var_dump($diff->format(
    "%y years %m months %d days %H:%i:%s and %R%a total days”
));

Time Zones

Time zones can be a real pain to handle, but using the DateTime class, makes it a lot easier. 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 time zone that the DateTime exists within. You can then call the setTimezone() function to shift that date and time into the time zone you're interested in. This process is significantly easier than trying to determine the offsets yourself.

$date = new DateTime("2022-12-01 00:00:00", new DateTimeZone("UTC"));
$date->setTimezone(new DateTimeZone("America/Detroit"));

DateTimeImmutable versus DateTime

PHP also supports a DateTimeImmutable class which provides an immutable version of the date. I like the immutable version because it's impossible for a function to modify the variable and thus add bugs to our code. Modifying an immutable class returns a new version of the class while keeping the old one intact.

Extending

Now I'm constantly using the same operations on the DateTimes inside of my project and I hate duplication. To prevent duplication, I create my own DateTime class.

namespace App\\Types;

class DateTimeImmutable extends \\DateTimeImmutable
{

}

$date = new DateTimeImmutable();

For example, in my project, I have two types of formats that I use constantly the MySQL format and the user-facing version. I create a formatMySql() and a formatUserFacing() functions inside of my DateTime class to handle this.

namespace App\\Types;

class DateTimeImmutable extends \\DateTimeImmutable
{
    public function formatMySql(): string
    {
        return $this->format("Y-m-d H:i:s");
    }

    public function formatUserFacing(): string
    {
        return $this->format("m/d/Y H:i");
    }
}

If you want to show data differently to our end users, we just have to change the function in one spot.

Iterating Over a Date Range

If you need to work on a set of dates between two dates, you can use the DatePeriod class to loop through every day within that range.

For example, if you need to do something for every date in December, you can do the following.

This example just outputs the date, but you can do any kind of calculation inside the foreach loop.

$startDate = new DateTime("2022-12-01");
$endDate = new DateTime("2023-01-01");
$interval = new DateInterval("P1D");

$period = new DatePeriod($startDate, $interval, $endDate);

foreach ($period as $currentDate) {
    echo $currentDate->format("m/d"), " ";
}

What You Need to Know

  • PHP provides support for date manipulation and math using the DateTime classes
  • Multiple functions to manipulate the dates
  • Support for time zones out of the box
  • You can extend it to add your logic

Tags: ,
 

Leave a comment

Use the form below to leave a comment: