gmdate
Formats a Unix timestamp as a string in UTC, ignoring the script's default timezone.
gmdate(string $format, ?int $timestamp = null): string- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$format | string | The output format, using the same characters as date(). |
$timestampoptional | ?int= null | A Unix timestamp in seconds. When omitted or null the current time is used. |
Return value
stringThe formatted date string, with the timestamp interpreted in UTC rather than the default timezone.
Errors
Does not throw. An unrecognised format character is copied to the output unchanged.
Changelog
- PHP 8.0The timestamp parameter became nullable. Passing null now means the current time; in PHP 7 an explicit null was cast to 0 and produced 1 January 1970.
gmdate is date with the timezone pinned to UTC. Same format characters, same arguments, same return type — the only difference is that the default timezone is ignored, so the output is identical on every server no matter how date.timezone is configured.
When to reach for it
Use it whenever the string leaves your application. HTTP headers such as Last-Modified and Expires are defined in GMT. So are cookie expiry strings, many API payloads, RSS pubDate elements and signature payloads for services like S3. Building those with date produces a header that is silently hours off whenever the server is not configured for UTC.
It is also the safest choice for anything a machine will parse back later, since the reader does not have to know your server's zone.
What it does not do
gmdate does not convert a local time to UTC. It formats an existing timestamp, and a timestamp is already an absolute instant with no zone attached. Timezone-aware output for offsets other than UTC needs DateTimeImmutable::setTimezone().
The e and T characters always report UTC and GMT respectively, so a round trip through strtotime will not lose the offset.
Example
When to use it
- Building an HTTP Last-Modified or Expires header, which the spec requires in GMT
- Writing an RFC 3339 timestamp with a Z suffix into an API request body
- Producing log timestamps that stay comparable across servers in different regions
Frequently asked questions
What is the difference between date and gmdate?
gmdate always formats in UTC while date uses the script's default timezone. They return the same string only when the default timezone is UTC.
Does gmdate convert my local time to UTC?
No. A Unix timestamp has no timezone, so gmdate only chooses how to render it. To convert a local wall-clock time, build it with gmmktime or use DateTimeImmutable with an explicit DateTimeZone.
How do I format an HTTP date header in PHP?
Use gmdate('D, d M Y H:i:s', $ts) and append ' GMT', or gmdate(DATE_RFC7231, $ts). The HTTP spec requires GMT, so date() would produce an incorrect header on a non-UTC server.
More examples
Caching headers that do not drift with the server timezone
The last line shows the bug this function prevents: date() renders Chicago local time but the header claims GMT, so caches would treat the resource as five hours older than it is.
<?php
date_default_timezone_set('America/Chicago');
$modified = 1751630400;
$expires = $modified + 3600;
echo 'Last-Modified: ', gmdate('D, d M Y H:i:s', $modified), " GMT\n";
echo 'Expires: ', gmdate('D, d M Y H:i:s', $expires), " GMT\n";
echo 'wrong (date): ', date('D, d M Y H:i:s', $modified), " GMT\n";Same instant across a DST boundary
Helsinki is UTC+2 in winter and UTC+3 in summer, so date() shifts by an hour between the two while gmdate stays fixed at 12:00. UTC output is what makes stored timestamps comparable.
<?php
date_default_timezone_set('Europe/Helsinki');
$winter = 1736078400; // 2025-01-05 12:00:00 UTC
$summer = 1751630400; // 2025-07-04 12:00:00 UTC
foreach (['winter' => $winter, 'summer' => $summer] as $label => $ts) {
printf("%-7s local %s | utc %s\n", $label, date('H:i T', $ts), gmdate('H:i T', $ts));
}Formatting a duration
Treating a duration as an offset from the epoch and formatting it in UTC turns 9045 seconds into 02:30:45. It only works below 24 hours, since the format has nowhere to put the days.
<?php
$seconds = 9045;
echo gmdate('H:i:s', $seconds), "\n";
echo gmdate('i:s', 185), "\n";
echo 'hours only: ', gmdate('G', $seconds), "\n";
Discussion