Skip to content

PHP Date and Time

Handling dates and times is a common task in web development. PHP provides both procedural functions and a powerful object-oriented API to manage dates, times, and timezones effectively.

The Modern Approach: DateTimeImmutable and DateTime

Section titled “The Modern Approach: DateTimeImmutable and DateTime”

The recommended way to work with dates and times in modern PHP is using the built-in DateTimeImmutable (preferred for immutability) and DateTime classes. They offer a robust, object-oriented interface.

Why DateTimeImmutable? Instances of DateTimeImmutable cannot be changed after creation. Methods like modify() or setTimezone() return a new object with the changes, leaving the original untouched. This prevents accidental modifications and makes code easier to reason about.

Example: Getting and Formatting the Current Date/Time:

<?php
// Use DateTimeImmutable for best practice
$now = new DateTimeImmutable(); // Creates an object representing the current date and time
// Format the date and time using the format() method
echo "Today is: " . $now->format('Y-m-d') . "<br>"; // e.g., 2023-10-27
echo "Current time: " . $now->format('H:i:s') . "<br>"; // e.g., 14:35:02 (24-hour)
echo "Full date and time: " . $now->format('l, F j, Y g:i a') . "<br>"; // e.g., Friday, October 27, 2023 2:35 pm
?>
  • Y - A full numeric representation of a year, 4 digits (e.g., 2023)
  • m - Numeric representation of a month, with leading zeros (01 to 12)
  • d - Day of the month, 2 digits with leading zeros (01 to 31)
  • l (lowercase ‘L’) - A full textual representation of the day of the week (e.g., Sunday)
  • H - 24-hour format of an hour with leading zeros (00 to 23)
  • h - 12-hour format of an hour with leading zeros (01 to 12)
  • i - Minutes with leading zeros (00 to 59)
  • s - Seconds with leading zeros (00 to 59)
  • a - Lowercase Ante meridiem and Post meridiem (am or pm)
  • U - Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)

Find a complete list of formatting characters in the PHP documentation for DateTimeInterface::format().

Servers might be located in different timezones than your users. PHP’s default timezone can be set in php.ini, but it’s best practice to handle timezones explicitly in your application.

Setting the Default Timezone (Script-level):

<?php
// Set the default timezone for all date/time functions in this script
date_default_timezone_set('America/New_York');
$now = new DateTimeImmutable();
echo "The time in New York is " . $now->format('H:i:sa') . "<br>";
// You can find supported timezone identifiers here: https://www.php.net/manual/en/timezones.php
?>

Working with Specific Timezones using DateTimeZone:

<?php
// Create timezone objects
$londonTimezone = new DateTimeZone('Europe/London');
$tokyoTimezone = new DateTimeZone('Asia/Tokyo');
// Create a DateTimeImmutable object (defaults to server/PHP timezone)
$now = new DateTimeImmutable();
// Create new DateTimeImmutable objects representing the *same instant* in different timezones
$nowInLondon = $now->setTimezone($londonTimezone);
$nowInTokyo = $now->setTimezone($tokyoTimezone);
echo "Current server time: " . $now->format('Y-m-d H:i:s P') . "<br>";
echo "Current London time: " . $nowInLondon->format('Y-m-d H:i:s P') . "<br>";
echo "Current Tokyo time: " . $nowInTokyo->format('Y-m-d H:i:s P') . "<br>";
?>

Creating Dates from Strings and Timestamps

Section titled “Creating Dates from Strings and Timestamps”

You often need to create date objects from existing data, like user input or database values.

From Specific Formats (Recommended):

Use DateTimeImmutable::createFromFormat() for reliable parsing when you know the exact format of the input string.

<?php
$dateString = "2024-01-15 10:30:00";
$format = 'Y-m-d H:i:s';
$dateObject = DateTimeImmutable::createFromFormat($format, $dateString);
if ($dateObject) {
echo "Created date: " . $dateObject->format('l, F j, Y') . "<br>"; // Outputs: Monday, January 15, 2024
} else {
echo "Failed to parse date string.";
// See DateTimeImmutable::getLastErrors() for details
// print_r(DateTimeImmutable::getLastErrors());
}
?>

From Flexible Strings (Use with Caution):

The DateTimeImmutable constructor (and the older strtotime() function) can parse many human-readable formats, but can be ambiguous.

<?php
try {
$d1 = new DateTimeImmutable("10:30pm April 15 2024");
echo "Created date 1: " . $d1->format('Y-m-d H:i:s') . "<br>";
$d2 = new DateTimeImmutable("tomorrow");
echo "Tomorrow is: " . $d2->format('Y-m-d') . "<br>";
$d3 = new DateTimeImmutable("+3 Months");
echo "Date in 3 months: " . $d3->format('Y-m-d') . "<br>";
// Ambiguous format (is it DD-MM-YYYY or MM-DD-YYYY?)
// $d4 = new DateTimeImmutable('10-11-12'); // Risky!
} catch (Exception $e) {
echo 'Error creating date: ' . $e->getMessage();
}
?>

Warning: Parsing ambiguous formats like ‘m/d/y’ or ‘d-m-y’ heavily depends on system settings and can lead to unexpected results. Always prefer createFromFormat() when possible.

From Unix Timestamps:

A Unix timestamp is the number of seconds since January 1, 1970 00:00:00 UTC.

<?php
$timestamp = 1678886400; // Example timestamp (March 15, 2023 12:00:00 UTC)
// Create from timestamp
$dateFromTimestamp = new DateTimeImmutable("@" . $timestamp);
// Set timezone if needed (timestamp is always UTC)
$dateFromTimestamp = $dateFromTimestamp->setTimezone(new DateTimeZone('Europe/Paris'));
echo "Date from timestamp: " . $dateFromTimestamp->format('Y-m-d H:i:s P') . "<br>";
?>

DateTimeImmutable objects can be easily modified, and differences calculated.

<?php
$today = new DateTimeImmutable();
// Modify returns a *new* object
$nextWeek = $today->modify('+1 week');
$yesterday = $today->modify('-1 day');
$threeMonthsLater = $today->modify('+3 months');
echo "Today: " . $today->format('Y-m-d') . "<br>";
echo "Next Week: " . $nextWeek->format('Y-m-d') . "<br>";
echo "Yesterday: " . $yesterday->format('Y-m-d') . "<br>";
echo "Three Months Later: " . $threeMonthsLater->format('Y-m-d') . "<br>";
// Calculate the difference between two dates
$date1 = new DateTimeImmutable('2024-07-04');
$date2 = new DateTimeImmutable('now');
$interval = $date2->diff($date1); // Returns a DateInterval object
// Format the interval
echo "Difference: " . $interval->format('%R%a days') . "<br>"; // e.g., +68 days or -10 days
if ($date1 > $date2) {
echo "There are " . $interval->days . " total days until July 4th.<br>";
} else {
echo "July 4th has passed by " . $interval->days . " total days.<br>";
}
?>

The modify() method accepts various relative formats (like those used by strtotime()). The diff() method returns a DateInterval object, which has properties for years, months, days, hours, etc., and a format() method.

Legacy Functions: date(), strtotime(), mktime()

Section titled “Legacy Functions: date(), strtotime(), mktime()”

While the DateTimeImmutable API is preferred, you will still encounter the older procedural functions:

  • date(format, timestamp): Formats a Unix timestamp (or the current time if timestamp is omitted). Simple for quick formatting but lacks the power of the object API.
  • strtotime(time_string): Parses a human-readable string into a Unix timestamp. Convenient but can be unreliable with ambiguous formats.
  • mktime(h, i, s, m, d, y): Gets the Unix timestamp for a specific date and time based on provided components. Less intuitive than the object approach.

Example using date() and strtotime():

<?php
date_default_timezone_set('UTC'); // Good practice to set timezone
// Simple formatting with date()
echo "Today is " . date("Y/m/d") . "<br>";
echo "The time is " . date("h:i:sa") . "<br>";
// Automatic Copyright Year
echo "&copy; 2010-" . date("Y") . "<br>";
// Using strtotime()
$timestampNextSaturday = strtotime("next Saturday");
if ($timestampNextSaturday !== false) {
echo "Next Saturday is: " . date("Y-m-d", $timestampNextSaturday) . "<br>";
} else {
echo "Could not parse 'next Saturday'.<br>";
}
?>

While these functions can be useful for simple tasks or legacy code, strive to use DateTimeImmutable for new development due to its clarity, robustness, and feature set.

For a complete reference of all date and time classes and functions, including detailed explanations and examples, consult the official PHP documentation: