9 use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK );
11 $VERSION = eval $VERSION;
12 @ISA = qw( Exporter );
13 @EXPORT = qw( timegm timelocal );
14 @EXPORT_OK = qw( timegm_nocheck timelocal_nocheck );
16 my @MonthDays = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
18 # Determine breakpoint for rolling century
19 my $ThisYear = ( localtime() )[5];
20 my $Breakpoint = ( $ThisYear + 50 ) % 100;
21 my $NextCentury = $ThisYear - $ThisYear % 100;
22 $NextCentury += 100 if $Breakpoint < 50;
23 my $Century = $NextCentury - 100;
26 my ( %Options, %Cheat );
28 use constant SECS_PER_MINUTE => 60;
29 use constant SECS_PER_HOUR => 3600;
30 use constant SECS_PER_DAY => 86400;
32 my $MaxInt = ( ( 1 << ( 8 * $Config{intsize} - 2 ) ) -1 ) * 2 + 1;
33 my $MaxDay = int( ( $MaxInt - ( SECS_PER_DAY / 2 ) ) / SECS_PER_DAY ) - 1;
35 if ( $^O eq 'MacOS' ) {
36 # time_t is unsigned...
37 $MaxInt = ( 1 << ( 8 * $Config{intsize} ) ) - 1;
40 $MaxInt = ( ( 1 << ( 8 * $Config{intsize} - 2 ) ) - 1 ) * 2 + 1;
43 # Determine the EPOC day for this machine
46 # work around posix-977 -- VOS doesn't handle dates in the range
48 $Epoc = _daygm( 0, 0, 0, 1, 0, 70, 4, 0 );
50 elsif ( $^O eq 'MacOS' ) {
51 $MaxDay *=2 if $^O eq 'MacOS'; # time_t unsigned ... quick hack?
52 # MacOS time() is seconds since 1 Jan 1904, localtime
53 # so we need to calculate an offset to apply later
55 $SecOff = timelocal( localtime(0)) - timelocal( gmtime(0) ) ;
56 $Epoc += _daygm( gmtime(0) );
59 $Epoc = _daygm( gmtime(0) );
62 %Cheat = (); # clear the cache as epoc has changed
66 # This is written in such a byzantine way in order to avoid
67 # lexical variables and sub calls, for speed
69 $Cheat{ pack( 'ss', @_[ 4, 5 ] ) } ||= do {
70 my $month = ( $_[4] + 10 ) % 12;
71 my $year = $_[5] + 1900 - $month / 10;
77 + ( ( ( $month * 306 ) + 5 ) / 10 )
86 $SecOff + $_[0] + ( SECS_PER_MINUTE * $_[1] ) + ( SECS_PER_HOUR * $_[2] );
88 return $sec + ( SECS_PER_DAY * &_daygm );
92 my ( $sec, $min, $hour, $mday, $month, $year ) = @_;
94 if ( $year >= 1000 ) {
97 elsif ( $year < 100 and $year >= 0 ) {
98 $year += ( $year > $Breakpoint ) ? $Century : $NextCentury;
101 unless ( $Options{no_range_check} ) {
102 if ( abs($year) >= 0x7fff ) {
105 "Cannot handle date ($sec, $min, $hour, $mday, $month, *$year*)";
108 croak "Month '$month' out of range 0..11"
112 my $md = $MonthDays[$month];
114 unless $month != 1 or $year % 4 or !( $year % 400 );
116 croak "Day '$mday' out of range 1..$md" if $mday > $md or $mday < 1;
117 croak "Hour '$hour' out of range 0..23" if $hour > 23 or $hour < 0;
118 croak "Minute '$min' out of range 0..59" if $min > 59 or $min < 0;
119 croak "Second '$sec' out of range 0..59" if $sec > 59 or $sec < 0;
122 my $days = _daygm( undef, undef, undef, $mday, $month, $year );
124 unless ($Options{no_range_check} or abs($days) < $MaxDay) {
126 $msg .= "Day too big - $days > $MaxDay\n" if $days > $MaxDay;
129 $msg .= "Cannot handle date ($sec, $min, $hour, $mday, $month, $year)";
136 + ( SECS_PER_MINUTE * $min )
137 + ( SECS_PER_HOUR * $hour )
138 + ( SECS_PER_DAY * $days );
142 local $Options{no_range_check} = 1;
148 my $loc_t = _timegm( localtime($ref_t) );
150 # Is there a timezone offset from GMT or are we done?
151 my $zone_off = $ref_t - $loc_t
154 # This hack is needed to always pick the first matching time
155 # during a DST change when time would otherwise be ambiguous
156 $zone_off -= SECS_PER_HOUR if $ref_t >= SECS_PER_HOUR;
158 # Adjust for timezone
159 $loc_t = $ref_t + $zone_off;
161 # Are we close to a DST change or are we done
162 my $dst_off = $ref_t - _timegm( localtime($loc_t) )
165 # Adjust for DST change
168 return $loc_t if $dst_off >= 0;
170 # for a negative offset from GMT, and if the original date
171 # was a non-extent gap in a forward DST jump, we should
172 # now have the wrong answer - undo the DST adjust;
173 my ( $s, $m, $h ) = localtime($loc_t);
174 $loc_t -= $dst_off if $s != $_[0] || $m != $_[1] || $h != $_[2];
179 sub timelocal_nocheck {
180 local $Options{no_range_check} = 1;
190 Time::Local - efficiently compute time from local and GMT time
194 $time = timelocal($sec,$min,$hour,$mday,$mon,$year);
195 $time = timegm($sec,$min,$hour,$mday,$mon,$year);
199 These routines are the inverse of built-in perl functions localtime()
200 and gmtime(). They accept a date as a six-element array, and return
201 the corresponding time(2) value in seconds since the system epoch
202 (Midnight, January 1, 1970 GMT on Unix, for example). This value can
203 be positive or negative, though POSIX only requires support for
204 positive values, so dates before the system's epoch may not work on
205 all operating systems.
207 It is worth drawing particular attention to the expected ranges for
208 the values provided. The value for the day of the month is the actual
209 day (ie 1..31), while the month is the number of months since January
210 (0..11). This is consistent with the values returned from localtime()
213 The timelocal() and timegm() functions perform range checking on the
214 input $sec, $min, $hour, $mday, and $mon values by default. If you
215 are confident that your data is good, you can explicitly import the
216 timelocal_nocheck() and timegm_nocheck() functions, which may provide
217 a small performance improvement.
219 use Time::Local 'timelocal_nocheck';
221 # The 365th day of 1999
222 print scalar localtime timelocal_nocheck 0,0,0,365,0,99;
224 Strictly speaking, the year should also be specified in a form
225 consistent with localtime(), i.e. the offset from 1900. In order to
226 make the interpretation of the year easier for humans, however, who
227 are more accustomed to seeing years as two-digit or four-digit values,
228 the following conventions are followed:
234 Years greater than 999 are interpreted as being the actual year,
235 rather than the offset from 1900. Thus, 1964 would indicate the year
236 Martin Luther King won the Nobel prize, not the year 3864.
240 Years in the range 100..999 are interpreted as offset from 1900,
241 so that 112 indicates 2012. This rule also applies to years less than zero
242 (but see note below regarding date range).
246 Years in the range 0..99 are interpreted as shorthand for years in the
247 rolling "current century," defined as 50 years on either side of the
248 current year. Thus, today, in 1999, 0 would refer to 2000, and 45 to
249 2045, but 55 would refer to 1955. Twenty years from now, 55 would
250 instead refer to 2055. This is messy, but matches the way people
251 currently think about two digit dates. Whenever possible, use an
252 absolute four digit year instead.
256 The scheme above allows interpretation of a wide range of dates,
257 particularly if 4-digit years are used.
259 Please note, however, that the range of dates that can be actually be
260 handled depends on the size of an integer (time_t) on a given
261 platform. Currently, this is 32 bits for most systems, yielding an
262 approximate range from Dec 1901 to Jan 2038.
264 Both timelocal() and timegm() croak if given dates outside the
267 =head2 Ambiguous Local Times (DST)
269 Because of DST changes, there are many time zones where the same local
270 time occurs for two different GMT times on the same day. For example,
271 in the "Europe/Paris" time zone, the local time of 2001-10-28 02:30:00
272 can represent either 2001-10-28 00:30:00 GMT, B<or> 2001-10-28
275 When given an ambiguous local time, the timelocal() function should
276 always return the epoch for the I<earlier> of the two possible GMT
279 =head2 Non-Existent Local Times (DST)
281 When a DST change causes a locale clock to skip one hour forward,
282 there will be an hour's worth of local times that don't exist. Again,
283 for the "Europe/Paris" time zone, the local clock jumped from
284 2001-03-25 01:59:59 to 2001-03-25 03:00:00.
286 If the timelocal() function is given a non-existent local time, it
287 will simply return an epoch value for the time one hour later.
289 =head2 Negative Epoch Values
291 Negative epoch (time_t) values are not officially supported by the
292 POSIX standards, so this module's tests do not test them. On some
293 systems, they are known not to work. These include MacOS (pre-OSX)
296 On systems which do support negative epoch values, this module should
297 be able to cope with dates before the start of the epoch, down the
298 minimum value of time_t for the system.
300 =head1 IMPLEMENTATION
302 These routines are quite efficient and yet are always guaranteed to
303 agree with localtime() and gmtime(). We manage this by caching the
304 start times of any months we've seen before. If we know the start
305 time of the month, we can always calculate any time within the month.
306 The start times are calculated using a mathematical formula. Unlike
307 other algorithms that do multiple calls to gmtime().
309 timelocal() is implemented using the same cache. We just assume that
310 we're translating a GMT time, and then fudge it when we're done for
311 the timezone and daylight savings arguments. Note that the timezone
312 is evaluated for each date because countries occasionally change their
313 official timezones. Assuming that localtime() corrects for these
314 changes, this routine will also be correct.
318 The whole scheme for interpreting two-digit years can be considered a
323 Support for this module is provided via the datetime@perl.org email
324 list. See http://lists.perl.org/ for more details.
326 Please submit bugs using the RT system at rt.cpan.org, or as a last
327 resort, to the datetime@perl.org list.
331 This module is based on a Perl 4 library, timelocal.pl, that was
332 included with Perl 4.036, and was most likely written by Tom
335 The current version was written by Graham Barr.
337 It is now being maintained separately from the Perl core by Dave
338 Rolsky, <autarch@urth.org>.