gmmktime
Builds a Unix timestamp from date and time parts interpreted as UTC rather than local time.
gmmktime(int $hour, ?int $minute = null, ?int $second = null, ?int $month = null, ?int $day = null, ?int $year = null): int|false- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$hour | int | Hour relative to the start of the day. Values outside 0-23 roll over into neighbouring days. |
$minuteoptional | ?int= null | Minute relative to the start of the hour. Defaults to the current minute in UTC when null. |
$secondoptional | ?int= null | Second relative to the start of the minute. Defaults to the current second in UTC when null. |
$monthoptional | ?int= null | Month number. Defaults to the current UTC month when null; values outside 1-12 roll over into other years. |
$dayoptional | ?int= null | Day of the month. Defaults to the current UTC day when null; values outside the month's range roll over. |
$yearoptional | ?int= null | The full year. Defaults to the current UTC year when null. |
Return value
int|falseThe Unix timestamp for the given UTC date and time, or false if the result does not fit in a PHP integer.
Errors
Throws an ArgumentCountError when called with no arguments. Returns false when the resulting timestamp cannot be represented as a PHP integer.
Changelog
- PHP 8.0hour is no longer optional — calling gmmktime() with no arguments throws an ArgumentCountError. The remaining parameters became nullable.
gmmktime is mktime with the parts read as UTC. Same argument order — hour, minute, second, month, day, year — and the same rollover behaviour, but no dependence on date.timezone, so it returns the same timestamp on every machine.
When to reach for it
Use it when the date parts you hold are already UTC: components pulled out of an API payload, a database column stored in UTC, or a fixed constant such as an epoch boundary in a test. Using mktime for those quietly shifts the result by the server's offset, and the bug only surfaces after a deployment to a differently configured host.
Rollover as a feature
Out-of-range parts are normalised rather than rejected. Month 13 becomes January of the next year, day 0 becomes the last day of the previous month, and hour 25 becomes 1am the following day. That makes date arithmetic easy — gmmktime(0, 0, 0, $m + 1, 0, $y) is the last day of month $m — but it also means gmmktime will never tell you the input was wrong. Validate with checkdate first if the numbers came from a user.
The odd hour-first, then month-day-year argument order is a frequent source of transposed arguments.
Example
When to use it
- Turning UTC date parts from a third-party API payload into a timestamp
- Pinning a fixed moment in a test so it does not depend on the runner's timezone
- Computing the last day of a month by asking for day 0 of the next one
Frequently asked questions
What is the difference between mktime and gmmktime?
mktime reads the parts as local time in the default timezone, while gmmktime reads them as UTC. They return the same timestamp only when the default timezone is UTC.
What is the argument order for gmmktime?
hour, minute, second, month, day, year. The time comes first and month precedes day, which is the usual cause of transposed-argument bugs.
Does gmmktime reject invalid dates?
No. Out-of-range values roll over — 30 February becomes 2 March and month 13 becomes the next January. Call checkdate first if the values came from user input.
More examples
Rollover arithmetic
Every out-of-range value is normalised instead of rejected. Day 0 of March is the last day of February, which correctly gives 28 in 2025 and 29 in the leap year 2024.
<?php
echo 'month 13 of 2025: ', gmdate('Y-m-d', gmmktime(0, 0, 0, 13, 1, 2025)), "\n";
echo 'day 0 of March 2025: ', gmdate('Y-m-d', gmmktime(0, 0, 0, 3, 0, 2025)), "\n";
echo 'last day of Feb 2024: ', gmdate('Y-m-d', gmmktime(0, 0, 0, 3, 0, 2024)), "\n";
echo 'hour 25 on 1 Jan: ', gmdate('Y-m-d H:i', gmmktime(25, 0, 0, 1, 1, 2025)), "\n";Round-tripping UTC parts
The parts go in as UTC and come back out unchanged through gmdate, even though the script's default timezone is UTC+5:30. mktime would have produced a timestamp 5.5 hours earlier.
<?php
date_default_timezone_set('Asia/Kolkata');
$payload = ['y' => 2025, 'm' => 12, 'd' => 25, 'h' => 6, 'i' => 30];
$ts = gmmktime($payload['h'], $payload['i'], 0, $payload['m'], $payload['d'], $payload['y']);
echo gmdate('D, d M Y H:i \U\T\C', $ts), "\n";
$back = gmdate('Y,n,j,G,i', $ts);
echo 'round trip: ', $back, "\n";
echo 'stable regardless of server zone: ', var_export($ts === 1766644200, true), "\n";Validate before you build
Without the checkdate guard, 30 February becomes 2 March and nothing signals a problem. gmmktime normalises silently, so validation has to happen before the call.
<?php
foreach ([[2, 30, 2025], [2, 28, 2025]] as [$m, $d, $y]) {
if (!checkdate($m, $d, $y)) {
echo "rejected {$y}-{$m}-{$d}\n";
continue;
}
echo 'accepted ', gmdate('Y-m-d', gmmktime(0, 0, 0, $m, $d, $y)), "\n";
}
echo 'unguarded: ', gmdate('Y-m-d', gmmktime(0, 0, 0, 2, 30, 2025)), "\n";
Discussion