Working with PHP Dates and the DateTime Class
Working with dates in any programming language can feel a bit intimidating. This article is intended to bolster your confidence with dates in PHP! In order to accomplish this, there are a few aspects of dates that we should explore together:
Don't have PHP installed just yet? Try this side dish before starting this one!
Dealing with Right Now
The quickest way work with dates lies in the present—how do I print the current date and time using PHP? There are a variety of ways, but the simplest is as follows:
<?php echo date('Y-m-d g:i:s a'); ?>
Right now the above might print something like:
Nifty, eh? But alright, there are a lot of seemingly random letters there. How does "Y-m-d g:i:s a" turn into !? Well I'm glad you asked—this is a very powerful feature afforded to us by the PHP date implementation.
Let's try a simpler one:
<?php echo date('Y'); ?>
This one just has the letter "Y", and will give us something like:
This is where the secret lies. Each letter in the string we pass into the date function will dictate how the date will output. What this means is that we have complete control over how we display our dates!
Date Format Character Table
Explore the table below, it contains the characters you can use in the date format string. Because resources like this, and in the official documentation here, you'll never have to memorize all of these. Bookmark a resource you like, and reference it when you need to format a date!
If you have JavaScript enabled, you can give it a try, below (try changing the text):
Category | Character | Description |
---|---|---|
Year | Y | four-digit year number |
y | two-digit year number | |
L | 1 if a leap year, 0 if not | |
Month | m | month number (with leading zero) |
n | month number (without leading zero) | |
F | full textual name of the month | |
M | three-letter textual name of the month | |
t | number of days in the month | |
Day | d | day of month (with leading zero) |
j | day of month (without leading zero) | |
l | full textual day of the week | |
D | three-letter textual day of the week | |
Hour | h | 12-hour clock hour (with leading zero) |
g | 12-hour clock hour (without leading zero) | |
a | lower-case am or pm | |
A | upper-case am or pm | |
H | 24-hour clock hour (with leading zero) | |
G | 24-hour clock hour (without leading zero) | |
I | 1 if in daylight savings time, 0 if not | |
Minute | i | minutes (with leading zero) |
Second | s | seconds (with leading zero) |
u | microseconds | |
U | number of seconds since the Unix Epoch | |
Other | N | numeric day of the week (1=Monday, 7=Sunday) |
w | numeric day of the week (0=Sunday, 6=Saturday) | |
S | suffix for the day of the month (st, nd, rd, th) | |
z | numeric day of the year (0-365) | |
W | ISO-8601 week number of the year (weeks starting with Monday) | |
o | ISO-8601 year number | |
b | Swatch Internet time (000-999) | |
e | timezone identifier | |
O | difference to Greenwich Time (GMT) in hours (+0000) | |
T | timezone abbreviation (EST) | |
Z | difference to Greenwich Time (GMT) in seconds (negative if west of UTC) | |
c | ISO-8601 date (1982-07-09T05:00:00+00:00) | |
r | RFC 2822 date (Fri, 09 Jul 1982 05:00:00 +0000) |
The DateTime and DateTimeZone Classes
We have seen that the date function in PHP is helpful for formatting the present time. It is common, however, in both world wide web sites and more complicated PHP applications that you may need to work with other dates and times as well. The modern approach to this in PHP is to make use of the DateTime class in PHP. This can be used to create date objects, which are pretty handy! Not only can they be easily stored in variables for later reference, they come with a format method, and you can easily adjust them and their associated timezone.
Let's suppose I wanted to store the release date for the film TRON from . There are a variety of formats you can use, but I like to use a nice human-readable format like: ""
Something incredible about the work put into the date functions and features of PHP is the allowance of many different formats of string in-order to form date objects. Observe how the above can be used to create a brand new PHP DateTime:
<?php $tronReleaseDateTime = new DateTime('1982-07-09 5:00pm'); ?>
That's all it takes to store the date and time in an object! Something to consider, though, is that this will use the default timezone. The default timezone may differ depending on the configuration of PHP or even the local time on your computer. If you want consistent results, it is best to specify a timezone. Luckily, this is easy too! Let's write the same example, but lets specify a timezone this time.
<?php
$tronReleaseDateTimeZone = new DateTimeZone('America/Edmonton');
$tronReleaseDateTime = new DateTime('1982-07-09 5:00pm', $tronReleaseDateTimeZone);
?>
Now your DateTimes will be more predictable, consider this a good practice. If you need the full list of supported timezones, please check the PHP manual here.
Now, the great thing about storing dates like this, is it becomes easy to format them. Using the table above, you can imagine all of the options we'd have for outputting this date how we'd like. Let's try a few!
<?php
$tronReleaseDateTimeZone = new DateTimeZone('America/Edmonton');
$tronReleaseDateTime = new DateTime('1982-07-09 5:00pm', $tronReleaseDateTimeZone);
echo $tronReleaseDateTime->format('Y');
// Outputs: 1982
echo $tronReleaseDateTime->format('Y-m-d');
// Outputs: 1982-07-09
echo $tronReleaseDateTime->format('g:i a');
// Outputs: 5:00 pm
echo $tronReleaseDateTime->format('c');
// Outputs: 1982-07-09T17:00:00-06:00
echo $tronReleaseDateTime->format('l F jS, Y @ g:i:s A');
// Outputs: Friday July 9th, 1982 @ 5:00:00 PM
?>
Hopefully that gives you some ideas on how you can both swiftly build DateTimes as well as output and represent them in your world wide web pages and PHP applications!
Past, Future, and Comparisons!
When looking to dates other than today, it is helpful to know what sort of words you can use when crafting a date. I had mentioned earlier that the the format we use for describing, creating, and storing a date is quite flexible. Let's create some DateTimes using some more interesting and dynamic dates and times:
<?php
$dateTimeZone = new DateTimeZone('America/Edmonton');
/**
* Past DateTimes:
*/
$firstDayOfLastMonth = new DateTime('first day of last month', $dateTimeZone);
echo $firstDayOfLastMonth->format('l F jS, Y g:i:s A');
// Outputs: Friday November 1st, 2024 9:06:01 AM
$secondThursdayOfLastMonth = new DateTime('second thursday of last month', $dateTimeZone);
echo $secondThursdayOfLastMonth->format('l F jS, Y g:i:s A');
// Outputs: Thursday November 14th, 2024 12:00:00 AM
$lastDayOfLastMonth = new DateTime('last day of last month', $dateTimeZone);
echo $lastDayOfLastMonth->format('l F jS, Y g:i:s A');
// Outputs: Saturday November 30th, 2024 9:06:01 AM
$lastHour = new DateTime('last hour', $dateTimeZone);
echo $lastHour->format('l F jS, Y g:i:s A');
// Outputs: Friday December 13th, 2024 8:06:01 AM
/**
* Future DateTimes:
*/
$firstDayOfNextMonth = new DateTime('first day of next month', $dateTimeZone);
echo $firstDayOfNextMonth->format('l F jS, Y g:i:s A');
// Outputs: Wednesday January 1st, 2025 9:06:01 AM
$secondThursdayOfNextMonth = new DateTime('second thursday of next month', $dateTimeZone);
echo $secondThursdayOfNextMonth->format('l F jS, Y g:i:s A');
// Outputs: Thursday January 9th, 2025 12:00:00 AM
$lastDayOfNextMonth = new DateTime('last day of next month', $dateTimeZone);
echo $lastDayOfNextMonth->format('l F jS, Y g:i:s A');
// Outputs: Friday January 31st, 2025 9:06:01 AM
$nextHour = new DateTime('next hour', $dateTimeZone);
echo $nextHour->format('l F jS, Y g:i:s A');
// Outputs: Friday December 13th, 2024 10:06:01 AM
?>
I encourage you to bring the above into a PHP file and experiment to see which phrases can help you achieve your goals!
Let's have a look at applying this in a realistic situation where you might want to display a start and end date:
<?php
$dateTimeZone = new DateTimeZone('America/Edmonton');
$startDate = new DateTime('next monday', $dateTimeZone);
$endDate = new DateTime(
// 5 weeks from the start date
$startDate->format(DATE_ATOM) . ' + 5 weeks',
$dateTimeZone
);
echo $startDate->format('Y-m-d'), ' - ', $endDate->format('Y-m-d');
// Outputs: 2024-12-16 - 2025-01-20
?>
Let's try the same, now with a time-of-day included:
<?php
$dateTimeZone = new DateTimeZone('America/Edmonton');
$startDateTime = new DateTime('now', $dateTimeZone);
$endDateTime = new DateTime(
$startDate->format(DATE_ATOM) . ' + 8 hours',
$dateTimeZone
);
echo $startDateTime->format('g:i A'), ' - ', $endDateTime->format('g:i A');
// Outputs: 9:06 AM - 5:06 PM
?>
The DateTime class comes with a modify method, which is great for updating an existing time on-the-fly. Consider this example:
<?php
$dateTimeZone = new DateTimeZone('America/Edmonton');
$formatString = 'l F jS, Y h:i A';
$dateTime new DateTime('now', $dateTimeZone);
echo 'Now: ', $dateTime->format($formatString);
// Outputs: Friday December 13th, 2024 04:06 PM
$dateTime->modify('+ 1 week');
echo '1 week later: ', $dateTime->format($formatString);
// Outputs: Friday December 20th, 2024 04:06 PM
$dateTime->modify('+ 3 hours');
echo '3 hours later: ', $dateTime->format($formatString);
// Outputs: Friday December 20th, 2024 07:06 PM
?>
In modern PHP we can even do comparisons. As a convenience you can compare using the standard comparison operators—check it out!
<?php
$dateTimeZone = new DateTimeZone('America/Edmonton');
$today = new DateTime('2024-12-13', $dateTimeZone); // 2024-12-13
$alsoToday = new DateTime('2024-12-13', $dateTimeZone); // 2024-12-13
echo var_dump($today == $alsoToday); // bool(false)
$nextWeek = new DateTime('next week', $dateTimeZone); // 2024-12-16
$lastWeek = new DateTime('last week', $dateTimeZone); // 2024-12-02
/**
* Try comparing our above DateTimes, what do we get?
*/
echo var_dump($nextWeek < $lastWeek); // bool(false)
echo var_dump($nextWeek == $lastWeek); // bool(false)
echo var_dump($nextWeek > $lastWeek); // bool(true)
echo var_dump($today < $lastWeek); // bool(false)
echo var_dump($today == $lastWeek); // bool(false)
echo var_dump($today > $lastWeek); // bool(true)
echo var_dump($today < $nextWeek); // bool(true)
echo var_dump($today == $nextWeek); // bool(false)
echo var_dump($today > $nextWeek); // bool(false)
?>