Dates7 min readExamples run on PHP 8.5.10

date()

Learn how PHP 8.4 date() turns an integer Unix timestamp into a formatted string, how timezones affect it, how to escape characters, and which mistakes to avoid.

Signature

date(string $format, ?int $timestamp = null): string

Purpose

date() converts a Unix timestamp, an integer count of seconds since 1970-01-01 00:00:00 UTC, into a human-readable string. You describe the layout with a format string such as Y-m-d H:i:s, and PHP replaces each recognized letter with the matching piece of the date or time. It is the quickest way to produce labels, log prefixes, file-name stamps and simple display dates.

The function always uses the current default timezone. A bare timestamp carries no timezone of its own, so the same integer can print as different wall-clock times depending on the configuration. When you need an explicit timezone attached to the value, the manual recommends DateTimeImmutable and its format() method.

Signature

Parameters and defaults

  • $format: a string using the same format characters as DateTimeInterface::format(). Letters with a meaning are expanded, and everything else is copied through as-is.
  • $timestamp: an optional integer Unix timestamp. If you omit it or pass null, PHP uses the current time, the same value time() returns. Since PHP 8.0 the parameter is explicitly nullable.

Because date() accepts only an integer, microseconds are not available: the u format character always yields 000000. Use a DateTimeImmutable object if you need real microseconds.

Return value and failure cases

date() returns a string. It does not return false for a bad format; unknown characters are simply copied. The notable failure is configuration related: if the active timezone is not valid, every date/time function emits an E_WARNING. Set a valid zone with date_default_timezone_set(). Passing a non-numeric string such as 'tomorrow' as the timestamp is a type error, so convert text with strtotime() first.

Example 1: common layouts

A fixed timestamp makes the result predictable. Here 962409600 is midnight UTC on 1 July 2000.

Example
<?php
date_default_timezone_set('UTC');
$timestamp = 962409600;

echo date('Y-m-d H:i:s', $timestamp) . "\n";
echo date('l, F jS, Y', $timestamp) . "\n";
echo date('D, d M y', $timestamp) . "\n";
Output
2000-07-01 00:00:00
Saturday, July 1st, 2000
Sat, 01 Jul 00

Useful characters include Y (four-digit year), y (two-digit year), m and d (zero-padded month and day), j and n (unpadded day and month), H (24-hour clock), h with A or a (12-hour clock), i (minutes), s (seconds), l and D (full and short weekday), and F and M (full and short month). Others include N (ISO weekday, 1 to 7), z (day of the year starting at 0), t (days in the month) and L (1 in a leap year).

Example 2: escaping literal text

To print a letter that would otherwise be a format character, put a backslash before it. Use single quotes so PHP does not treat sequences like \t as a tab before date() sees them.

Example
<?php
date_default_timezone_set('UTC');
$timestamp = 1000000000;

echo date('Y-m-d \a\t H:i', $timestamp) . "\n";
echo date('l \t\h\e jS \o\f F', $timestamp) . "\n";
echo date('H:m:s', $timestamp) . "\n";
Output
2001-09-09 at 01:46
Sunday the 9th of September
01:09:40

The last line shows a classic slip: the middle m means month, not minutes, so the output is 01:09:40 rather than 01:46:40. Minutes are i.

Example 3: the timezone changes the text

The timestamp stays the same, but the rendered wall-clock time follows the default timezone. T prints the abbreviation and P prints the offset from UTC.

Example
<?php
date_default_timezone_set('UTC');
$timestamp = 1000000000;
echo date('Y-m-d H:i:s T P', $timestamp) . "\n";

date_default_timezone_set('America/New_York');
echo date('Y-m-d H:i:s T P', $timestamp) . "\n";
Output
2001-09-09 01:46:40 UTC +00:00
2001-09-08 21:46:40 EDT -04:00

Edge cases

  • Omitting the timestamp makes the result depend on the current time, so tests should always pass a fixed integer.
  • Negative timestamps are valid and describe moments before 1970. For example, -86400 is one day before the epoch.
  • Y is the calendar year, while o is the ISO-8601 week-numbering year. Around the end and start of a year they can differ, so use o only together with the ISO week number W.
  • Daylight saving transitions can make local clock times repeat or skip, because date() formats the real instant in the active zone.
  • Characters without a current meaning may gain one in a future PHP release, so escape all literal letters.

Common mistakes

  1. Mixing up m (month) and i (minutes), or h (12-hour) and H (24-hour).
  2. Forgetting to escape words in the format, which turns letters into date pieces.
  3. Using double quotes around a format that contains backslashes, so the string is changed before date() receives it.
  4. Assuming a timestamp has a timezone. It does not; the default timezone is applied at format time.
  5. Expecting microseconds from date(); u is always 000000.
  6. Passing a date string instead of an integer. Convert it with strtotime() or mktime() first.
  • gmdate() formats in GMT/UTC regardless of the default timezone.
  • idate() returns a single date part as an integer.
  • getdate() returns date and time parts as an array.
  • mktime() builds a timestamp from components.
  • strtotime() parses text into a timestamp.
  • time() returns the current timestamp.
  • DateTimeImmutable::format() formats with an attached timezone and supports microseconds.
  • IntlDateFormatter::format() formats for other languages and locales.

Recap

date() takes a format string and an optional integer timestamp and always returns a string. It uses the default timezone, copies unknown characters through, and needs backslash escapes for literal letters. Pass fixed timestamps for repeatable results, set the timezone deliberately, and move to DateTimeImmutable when timezone information must travel with the value.

Tested examples

Common date layouts for a fixed timestamp
<?php
date_default_timezone_set('UTC');
$timestamp = 962409600;

echo date('Y-m-d H:i:s', $timestamp) . "\n";
echo date('l, F jS, Y', $timestamp) . "\n";
echo date('D, d M y', $timestamp) . "\n";
Output
2000-07-01 00:00:00
Saturday, July 1st, 2000
Sat, 01 Jul 00
Escaping literal text and the m versus i mistake
<?php
date_default_timezone_set('UTC');
$timestamp = 1000000000;

echo date('Y-m-d \a\t H:i', $timestamp) . "\n";
echo date('l \t\h\e jS \o\f F', $timestamp) . "\n";
echo date('H:m:s', $timestamp) . "\n";
Output
2001-09-09 at 01:46
Sunday the 9th of September
01:09:40
Same timestamp in two timezones
<?php
date_default_timezone_set('UTC');
$timestamp = 1000000000;
echo date('Y-m-d H:i:s T P', $timestamp) . "\n";

date_default_timezone_set('America/New_York');
echo date('Y-m-d H:i:s T P', $timestamp) . "\n";
Output
2001-09-09 01:46:40 UTC +00:00
2001-09-08 21:46:40 EDT -04:00