Dates7 min readExamples run on PHP 8.5.10

gmdate()

Learn how PHP gmdate() formats a Unix timestamp as a GMT/UTC string, how it differs from date(), and which mistakes to avoid.

Signature

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

Purpose

gmdate() turns a Unix timestamp into a formatted string in Greenwich Mean Time (GMT/UTC). It works like date(), with one difference: date() converts the timestamp into the script's default timezone, while gmdate() always uses UTC. That makes it a good choice when output must not depend on server configuration, for example in logs, cache keys, protocol headers or stored values.

Signature

Parameters and defaults

  • $format is the pattern describing the output. It uses the same format characters as date(), such as Y (four-digit year), m (month with leading zero), d (day with leading zero), H, i and s.
  • $timestamp is an optional integer Unix timestamp. If you omit it or pass null, PHP uses the current time, as time() would. Since PHP 8.0.0 the parameter is explicitly nullable.

Because the default depends on the current time, the examples below always pass a fixed timestamp so the results are repeatable.

Return value and failure cases

The function returns a string. Passing a value that cannot be used as an integer timestamp, such as a non-numeric string, raises a TypeError. Unrecognized format characters are not an error; they are copied to the output unchanged, which is why letters you want printed literally should be escaped with a backslash.

Example 1: the Unix epoch

Timestamp 0 is the start of the Unix epoch. In UTC that is midnight on 1 January 1970.

Example
<?php
echo gmdate("Y-m-d H:i:s", 0), "\n";
Output
1970-01-01 00:00:00

Example 2: date() versus gmdate()

The next script sets a non-UTC default timezone. The same timestamp is shown through both functions. date() follows the default timezone, so the result is shifted and even lands on a different calendar day. gmdate() ignores the setting.

Example
<?php
date_default_timezone_set('Europe/Helsinki');
$ts = 1700000000;
echo date('Y-m-d H:i:s', $ts), "\n";
echo gmdate('Y-m-d H:i:s', $ts), "\n";
Output
2023-11-15 00:13:20
2023-11-14 22:13:20

Example 3: calendar details and escaping

Format characters can expose more than the visible date. Here l is the full weekday name, L is 1 in a leap year, t is the number of days in the month, and z is the zero-based day of the year. The timestamp is 29 February 2000 at midnight UTC.

Example
<?php
echo gmdate('Y-m-d l L t z', 951782400), "\n";
echo gmdate('D, d M Y H:i:s \G\M\T', 86400 * 365), "\n";
Output
2000-02-29 Tuesday 1 29 59
Fri, 01 Jan 1971 00:00:00 GMT

The second line shows escaping: \G\M\T prints the literal letters GMT instead of treating them as format characters. This is the usual way to build an HTTP-style date string by hand.

Edge cases

  • Default timezone has no effect on the result. Changing it with date_default_timezone_set() affects date() but not gmdate().
  • Omitting the timestamp reads the clock. Anything built on it is non-deterministic, so pass an explicit timestamp in tests.
  • Literal text needs escaping. Letters such as T, D or d mean something to the formatter. Prefix each literal letter with a backslash, and remember that inside a double-quoted PHP string the backslash itself has to be written as \\ in some cases. Single quotes are often easier.
  • The input is a timestamp, not a date string. To format text such as 2024-05-01, convert it first, for example with gmmktime() or a DateTimeImmutable object.
  • Timestamps before 1970 are negative integers and format as earlier dates.

Common mistakes

  1. Assuming gmdate() and date() match. They only match when the default timezone is already UTC. Code that appears to work on one server may differ on another.
  2. Building a timestamp with mktime() and formatting it with gmdate(). mktime() interprets its arguments in the default timezone, while gmdate() prints UTC, so the printed hour can differ from the one you supplied. Use gmmktime() when both sides should be UTC.
  3. Passing milliseconds. Many systems, including JavaScript, produce millisecond timestamps. gmdate() expects seconds, so divide by 1000 and cast to int first.
  4. Forgetting to escape literal characters. An unescaped letter in the format may be replaced by a date part.
  5. Expecting timezone names to be consistent. If you need to show a zone label, prefer a literal escaped suffix like \G\M\T or \U\T\C that you control.
  • date() formats a timestamp in the default timezone.
  • mktime() builds a timestamp from local date parts.
  • gmmktime() builds a timestamp from GMT date parts.
  • DateTimeImmutable::__construct() creates an object-based date value.
  • DateTimeInterface::format() formats date objects with the same format syntax.

Recap

gmdate() takes a format string and an optional integer timestamp and returns a UTC-formatted string. Use it when the output must be independent of the configured timezone, pass fixed timestamps for predictable results, escape literal letters, and pair it with gmmktime() rather than mktime() when building timestamps from date parts.

Tested examples

Format the Unix epoch in UTC
<?php
echo gmdate("Y-m-d H:i:s", 0), "\n";
Output
1970-01-01 00:00:00
Compare date() and gmdate() with a non-UTC default timezone
<?php
date_default_timezone_set('Europe/Helsinki');
$ts = 1700000000;
echo date('Y-m-d H:i:s', $ts), "\n";
echo gmdate('Y-m-d H:i:s', $ts), "\n";
Output
2023-11-15 00:13:20
2023-11-14 22:13:20
Calendar format characters and escaped literal text
<?php
echo gmdate('Y-m-d l L t z', 951782400), "\n";
echo gmdate('D, d M Y H:i:s \G\M\T', 86400 * 365), "\n";
Output
2000-02-29 Tuesday 1 29 59
Fri, 01 Jan 1971 00:00:00 GMT