Time

gmtime#

Convert an epoch time to a broken-down UTC time, either as a 9-element list or as a ctime(3)-style string.

gmtime is localtime expressed in the Greenwich time zone. It takes an integer number of seconds since the epoch — the kind of value time returns — and hands back either the individual calendar fields (in list context) or a ready-to-print summary string (in scalar context). No time-zone lookup, no TZ, no DST: the result is always UTC.

Synopsis#

gmtime EXPR
gmtime

gmtime without an argument uses the current time.

What you get back#

In list context, a nine-element list drawn straight from the C struct tm:

#    0     1     2      3      4     5      6      7      8
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
    = gmtime(time);

Index

Field

Range

Notes

0

$sec

0..60

60 allows a positive leap second

1

$min

0..59

2

$hour

0..23

3

$mday

1..31

1-based

4

$mon

0..11

0-based — January is 0, December is 11

5

$year

years since 1900 — add 1900 for AD

6

$wday

0..6

Sunday is 0

7

$yday

0..365

0 is January 1st; 365 only in leap years

8

$isdst

0

always 0 for gmtime — UTC has no DST

In scalar context, a single ctime(3)-formatted English string:

my $s = gmtime;    # "Thu Oct 13 04:54:34 1994"

The scalar form is always English and locale-independent. For a locale-aware or differently-formatted string, build it from the list form with POSIX::strftime.

Global state it touches#

None. gmtime does not read $ENV{TZ}, does not consult the interpreter’s locale, and does not depend on or modify any of the Perl special variables. Given the same EXPR, it always returns the same result.

With no argument, it reads the current wall-clock time via time.

Examples#

Current UTC broken down into its fields, with the month-0-index and year-since-1900 traps both handled:

my @abbr = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my ($sec, $min, $hour, $mday, $mon, $year) = gmtime;
printf "%s %d, %d  %02d:%02d:%02d UTC\n",
       $abbr[$mon], $mday, $year + 1900, $hour, $min, $sec;
# e.g. "Apr 23, 2026  14:07:09 UTC"

The scalar form — a single fixed-format string, useful for logs:

my $stamp = gmtime;
print "[$stamp] startup\n";
# "[Thu Apr 23 14:07:09 2026] startup"

Format the list with POSIX::strftime when you want ISO-8601 or a locale-aware rendering:

use POSIX qw(strftime);
my $iso = strftime "%Y-%m-%dT%H:%M:%SZ", gmtime;
# e.g. "2026-04-23T14:07:09Z"

Convert a stored epoch (not the current time) — any integer seconds since 1970-01-01 UTC works:

my $epoch = 1_700_000_000;
my @t = gmtime($epoch);
printf "%04d-%02d-%02d\n", $t[5] + 1900, $t[4] + 1, $t[3];
# "2023-11-14"

$isdst is always 0 under gmtime — do not use it to probe DST. Call localtime if you need that information:

my $dst_here = (localtime)[8];   # 0 or 1 depending on local zone
my $dst_utc  = (gmtime)[8];      # always 0

Edge cases#

  • Bare call uses current time: gmtime with no argument is gmtime(time). Inside interpolation or a list that might swallow the call, parenthesise: gmtime().

  • List vs scalar context is load-bearing. In list context you get nine numbers; in scalar context you get a string. Forcing scalar on a bare call inside a list:

    print gmtime, "\n";                # nine digits, no spaces
    print scalar gmtime, "\n";         # "Thu Apr 23 14:07:09 2026"
    
  • $mon is 0-indexed, $year is since-1900. Two of the most common Perl bugs. For a full calendar year do $year + 1900; for a 1-indexed month do $mon + 1.

  • $mday is 1-indexed, $yday is 0-indexed. Mirrors C struct tm exactly — inconsistent, but stable.

  • $sec == 60 on a positive leap second. Code that validates with $sec <= 59 will reject legitimate values.

  • Negative epoch values represent dates before 1970-01-01 UTC and are accepted on platforms whose gmtime(3) accepts them — which Linux does. gmtime(-1) returns 1969-12-31 23:59:59 UTC.

  • Fractional seconds are discarded. EXPR is truncated toward zero before the conversion; gmtime(1.9) is gmtime(1). For sub-second precision, keep your own fractional part and format it separately.

  • No time-zone abbreviation in the scalar form. Unlike localtime’s ctime(3) output on some platforms, gmtime’s scalar form never includes a zone name. It is always the five-field "Wdy Mon DD HH:MM:SS YYYY" shape.

  • $isdst is always 0, not undef and not -1. Do not test it for truth under gmtime; the answer is meaningless.

Alternatives and companions#

  • Going the other way — from broken-down fields back to an epoch — is the job of the Time::Local module. Use timegm (UTC) or timelocal (local zone) there:

    use Time::Local qw(timegm);
    my $epoch = timegm($sec, $min, $hour, $mday, $mon, $year);
    
  • Object-oriented access by field name is offered by Time::Piece, which overloads localtime and gmtime to return objects with ->year, ->mon, ->mday etc. The field conventions there are adjusted — year is already the full year, mon is already 1-indexed — so code written against Time::Piece cannot be mixed casually with code written against the built-in list form.

  • Human-readable formatting belongs to POSIX::strftime; feed it the list returned by gmtime directly.

  • Comprehensive date arithmetic, time zones, durations — reach for DateTime on CPAN. gmtime is the minimum viable primitive; DateTime is the full library.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • localtime — same conversion, but in the local time zone; $isdst there is meaningful

  • time — produces the epoch value gmtime consumes

  • POSIX::strftime — format the 9-element list into an arbitrary date string (ISO-8601, locale-aware, etc.)

  • Time::Local — inverse operation: build an epoch from broken-down UTC or local fields

  • Time::Piece — object wrapper around gmtime / localtime with named accessors