The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

# You may distribute under the terms of either the GNU General Public License
# or the Artistic License (the same terms as Perl itself)
#
# (C) Paul Evans, 2012 -- leonerd@leonerd.org.uk
package Time::timegm;
use strict;
our $VERSION = '0.01';
use Exporter 'import';
our @EXPORT_OK = qw(
timegm
);
unless( eval {
require XSLoader;
XSLoader::load( __PACKAGE__, $VERSION );
defined Time::timegm::timegm( 0, 0, 0, 0, 1, 70 )
} ) {
# Fallback on pureperl implementation
require POSIX;
no warnings 'redefine';
*timegm = \&timegm_pp;
}
use Carp;
use POSIX qw( mktime );
# Number of seconds in a POSIX day
use constant DAY => 24*60*60;
use constant HOUR => 60*60;
use constant MIN => 60;
=head1 NAME
C<Time::timegm> - a UTC version of C<mktime()>
=head1 SYNOPSIS
use Time::timegm qw( timegm );
my $epoch = timegm( 0, 0, 0, 14, 6-1, 2012-1900 );
print "2012-06-14 00:00:00 UTC happened at ",
scalar localtime($epoch), " localtime\n";
=head1 DESCRIPTION
The L<POSIX> standard provides three functions for converting between integer
epoch values and 6-component "broken-down" time representations. C<localtime>
and C<gmtime> convert an epoch into the 6 components of seconds, minutes,
hours, day of month, month and year, in either local timezone or UTC. The
C<mktime> function converts a local broken-down time into an epoch value.
However, C<POSIX> does not provide a UTC version of this.
This module provides a function C<timegm> which has this ability.
Unlike some other CPAN implementations of this behaviour, this version does
not re-implement the time handling logic internally. It reuses the C<mktime>
and C<gmtime> functions provided by the system to ensure its results are
always consistent with the other functions.
=cut
=head1 FUNCTIONS
=cut
=head2 $epoch = timegm( $sec, $min, $hour, $mday, $mon, $year )
Returns the epoch integer value representing the time given by the 6
broken-down components.
As with C<POSIX::mktime> it is I<not> required that these values be within
their "valid" ranges. This function will normalise values out of range. For
example, the 25th hour of a day is normalised to the 1st hour of the following
day; or the 0th month is normalised to the 12th month of the preceeding year.
=cut
# Cache "$year/$mon" => $epoch of the time that month begins
my %start_of_month;
sub timegm_pp
{
my ( $sec, $min, $hour, $mday, $mon, $year ) = @_;
# Epoch times + UTC always align day boundaries at multiples of 86400. The
# structure is mathematically regular within a month. Therefore we can
# calculate the epoch time for a given time in UTC by finding the start of
# the month then adding seconds
$mon-=12, $year++ while $mon >= 12;
$mon+=12, $year-- while $mon < 0;
my $monstart = $start_of_month{"$year/$mon"};
unless( defined $monstart ) {
$monstart = mktime( 0, 0, 0, 1, $mon, $year );
$monstart -= $monstart % DAY;
my @gmtime = gmtime $monstart;
$gmtime[$_] == 0 or croak "Expected midnight GMT, did not get it - " . scalar( gmtime $monstart ) for 0 .. 2;
# Might have to round forward rather than backward
$monstart += DAY, @gmtime = gmtime $monstart if $gmtime[3] > 1;
$gmtime[3] == 1 or croak "Expected 1st of month GMT, did not get it - " . scalar( gmtime $monstart );
$start_of_month{"$year/$mon"} = $monstart;
}
return $monstart + ($mday-1)*DAY + $hour*HOUR + $min*MIN + $sec;
}
=head1 COMPARISON WITH Time::Local
The L<Time::Local> module also provides a function called C<timegm()> with
similar behaviour to this one. The differences are:
=over 2
=item *
C<Time::timegm::timegm()> handles denormalised values (that is, seconds or
minutes outside of the range 0 to 59, hours outside 0 to 23, etc..) by
adjusting the next largest unit (such that 61 seconds is 1 second of the next
minute, etc). C<Time::Local::timegm()> croaks on out-of-range input.
C<Time::Local> also provides a function C<timegm_nocheck()> which does not
croak but it is documented that the behavior is unspecified on out-of-range
values.
=item *
C<Time::timegm::timegm()> is implemented by a light XS wrapper around the
C<timegm(3)> or C<_mkgmtime(3)> function provided by the platform's C library
if such a function is provided, so its behaviour is consistent with the rest
of the platform. C<Time::Local> re-implements the logic in perl code.
C<Time::timegm> will fall back to a perl implementation only if the XS one
cannot be used.
=back
=head1 AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
=cut
0x55AA;