How do I format dates in PHP?
Short answer
Use DateTimeImmutable with an explicit timezone and format with ->format(). Store timestamps in UTC and convert for display.
$now = new DateTimeImmutable('now', new DateTimeZone('UTC'));
echo $now->format('Y-m-d H:i:s'); // 2026-03-15 14:30:00
echo $now->format('l, j F Y'); // Sunday, 15 March 2026
echo $now->format('c'); // ISO 8601#Why Immutable
DateTime methods modify the object in place and also return it, so this bug is easy to write:
$start = new DateTime('2026-01-01');
$end = $start->modify('+1 month'); // $start changed too!DateTimeImmutable returns a new object and leaves the original alone. Use it by default.
#Format characters worth knowing
Y y | 2026 / 26 |
m n | 03 / 3 |
d j | 05 / 5 |
H h | 24-hour / 12-hour |
i s | minutes / seconds |
D l | Mon / Monday |
M F | Mar / March |
A | AM or PM |
#Parsing
$d = new DateTimeImmutable('2026-03-15');
$d = DateTimeImmutable::createFromFormat('d/m/Y', '15/03/2026');Use createFromFormat when the input is ambiguous. 03/04/2026 is March or April depending on where you live; being explicit removes the guess.
#Differences
$diff = $start->diff($end);
echo $diff->days; // total days
echo $diff->format('%a days, %h hours');#Timezones
Store UTC in your database. Convert only for display:
$utc = new DateTimeImmutable($row['created_at'], new DateTimeZone('UTC'));
echo $utc->setTimezone(new DateTimeZone('America/New_York'))->format('g:i A');Storing local times means daylight saving transitions give you an hour that happens twice and an hour that never happens.