Dates7 min readExamples run on PHP 8.5.10

gmmktime()

Learn how gmmktime() turns GMT/UTC date and time parts into a Unix timestamp, how it normalizes overflowing values, and how it differs from mktime().

Signature

gmmktime(
    int $hour,
    ?int $minute = null,
    ?int $second = null,
    ?int $month = null,
    ?int $day = null,
    ?int $year = null
): int|false

Purpose

gmmktime() converts calendar parts (hour, minute, second, month, day, year) into a Unix timestamp, the number of seconds since 1970-01-01 00:00:00 GMT. The parts you pass are interpreted as a GMT/UTC date. The default timezone set with date_default_timezone_set() does not shift the meaning of your arguments.

It is the GMT counterpart of mktime(), which reads the same arguments as local time in the current default timezone. Use gmmktime() when you have a UTC wall-clock date and need a stable integer for storage, comparison or arithmetic.

Signature

Parameters and defaults

  • hour is required. Calling gmmktime() with no arguments throws an ArgumentCountError. If you want the current timestamp, use time().
  • minute, second, month, day and year are nullable and default to null. An omitted or null argument takes the current GMT value for that part. Arguments can only be left out from right to left.
  • Out-of-range values are not errors. They are interpreted relative to the surrounding unit:
    • Hours above 23 roll into the following days, and negative hours move back before midnight.
    • Minutes and seconds above 59 roll forward, and negative values roll backward.
    • Month 0 means December of the previous year, -1 means November, and months above 12 move into later years.
    • Day 0 means the last day of the previous month, -1 the day before that, and days beyond the month length move into following months.

Return value and failures

On success you get an int timestamp. The function returns false if the result does not fit in a PHP integer. Because the return type is int|false, check strictly with === false when you feed it extreme years. A timestamp of 0 is a valid result (the Unix epoch), so a loose truthiness test would misread it.

Example 1: a fixed GMT moment

The arguments run from the smallest unit to the largest for the time part, then month, day, year. Note that this is not the order of an ISO date string.

Example
<?php
date_default_timezone_set('UTC');
$ts = gmmktime(12, 30, 45, 7, 1, 2000);
echo $ts, "\n";
echo gmdate('Y-m-d H:i:s', $ts), "\n";
Output
962454645
2000-07-01 12:30:45

Use gmdate() to format the result, since it formats in GMT as well. Formatting with date() would apply the default timezone and might show a different clock time.

Example 2: normalizing overflowing values

Because values outside the usual ranges roll over, you can do calendar arithmetic without a lookup table. Month 14 of 2023 is February 2024, and day 0 of March is the last day of February, which handles leap years for you.

Example
<?php
$feb = gmmktime(0, 0, 0, 14, 1, 2023);
$leapEnd = gmmktime(0, 0, 0, 3, 0, 2024);
echo gmdate('Y-m-d', $feb), "\n";
echo gmdate('Y-m-d', $leapEnd), "\n";
Output
2024-02-01
2024-02-29

Example 3: independence from the default timezone

Here the default timezone is Asia/Tokyo, which is nine hours ahead of GMT. The same arguments give different timestamps with gmmktime() and mktime().

Example
<?php
date_default_timezone_set('Asia/Tokyo');
$gm = gmmktime(0, 0, 0, 1, 1, 2000);
$local = mktime(0, 0, 0, 1, 1, 2000);
echo json_encode(['gm' => $gm, 'local' => $local, 'difference' => $gm - $local]), "\n";
Output
{"gm":946684800,"local":946652400,"difference":32400}

Midnight in Tokyo happens nine hours before midnight GMT, so the local timestamp is 32400 seconds smaller.

Edge cases

  • Omitted arguments are not deterministic. Leaving out the day, for instance, fills in today's GMT day. That is convenient in a live app but makes tests unstable, so pass every part when you need repeatable results.
  • Two-digit years. Do not rely on short years such as 99. Pass a full four-digit year to avoid ambiguity.
  • Large years. On builds where the result cannot be represented as a PHP integer, the function returns false.
  • Local-time derivation. The manual notes that gmmktime() is built on mktime() internally, so only times valid in the derived local time can be used. If a precise, timezone-proof conversion matters in a critical path, consider DateTimeImmutable with an explicit UTC zone.

Common mistakes

  1. Using the wrong argument order. Writing gmmktime(2024, 5, 17, ...) as if it were year-month-day produces a wrong date silently, because the first parameter is the hour.
  2. Formatting with date() instead of gmdate(). The timestamp is correct, but the displayed clock time changes with the default timezone.
  3. Mixing mktime() and gmmktime(). Comparing timestamps from the two gives offsets equal to the timezone difference.
  4. Calling it with no arguments. Since PHP 8.0 hour is required, and the call throws ArgumentCountError. Use time() for the current moment.
  5. Treating 0 as failure. Use === false to detect failure.
  • mktime() builds a timestamp from local-time parts.
  • gmdate() formats a timestamp in GMT.
  • date() formats a timestamp in the default timezone.
  • time() returns the current timestamp.
  • DateTimeImmutable offers an object-oriented alternative with explicit timezones.

Recap

gmmktime() takes a GMT calendar date, starting with the required hour, and returns a Unix timestamp or false on integer overflow. Overflowing parts normalize into neighboring units, omitted parts use the current GMT values, and the default timezone does not change how the arguments are read. Pair it with gmdate() to keep everything in UTC.

Tested examples

A fixed GMT moment
<?php
date_default_timezone_set('UTC');
$ts = gmmktime(12, 30, 45, 7, 1, 2000);
echo $ts, "\n";
echo gmdate('Y-m-d H:i:s', $ts), "\n";
Output
962454645
2000-07-01 12:30:45
Normalizing overflowing values
<?php
$feb = gmmktime(0, 0, 0, 14, 1, 2023);
$leapEnd = gmmktime(0, 0, 0, 3, 0, 2024);
echo gmdate('Y-m-d', $feb), "\n";
echo gmdate('Y-m-d', $leapEnd), "\n";
Output
2024-02-01
2024-02-29
Independence from the default timezone
<?php
date_default_timezone_set('Asia/Tokyo');
$gm = gmmktime(0, 0, 0, 1, 1, 2000);
$local = mktime(0, 0, 0, 1, 1, 2000);
echo json_encode(['gm' => $gm, 'local' => $local, 'difference' => $gm - $local]), "\n";
Output
{"gm":946684800,"local":946652400,"difference":32400}