summaryrefslogtreecommitdiff
path: root/lib/Time
diff options
context:
space:
mode:
authorMichael G Schwern <schwern@pobox.com>2008-09-12 17:18:02 -0700
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2009-01-03 18:36:05 +0100
commita272e669f4b28ef6839df6dcd80d81421a1924dc (patch)
treed0114ac536208fcdbaff03440cf0e58e7e65f9b7 /lib/Time
parentb51c85cfecd5519fb69801887d6d6ebf80d9fce4 (diff)
downloadperl-a272e669f4b28ef6839df6dcd80d81421a1924dc.tar.gz
Patch in a 64 bit clean gmtime_r() and localtime_r() from the y2038 project. http://y2038.googlecode.com/ so Perl is no longer subject to the y2038 bug.
Use Quad_t for our 64 bit time_t replacement. Temporarily through out the "broken localtime work around". That will have to be integrated into localtime64_r(). Fix Time::Local to handle the new expanded date range. "use integer" had to go as it pegged scalars to 32 bit integers which aren't large enough to hold the new time range. There are probably portability issues. timegm, for example, is not portable. Also the assumption that "long" is 64 bits is probably wrong.
Diffstat (limited to 'lib/Time')
-rw-r--r--lib/Time/Local.pm20
-rwxr-xr-xlib/Time/Local.t37
2 files changed, 24 insertions, 33 deletions
diff --git a/lib/Time/Local.pm b/lib/Time/Local.pm
index 4044cd9c9a..b83bb1a7dd 100644
--- a/lib/Time/Local.pm
+++ b/lib/Time/Local.pm
@@ -4,7 +4,6 @@ require Exporter;
use Carp;
use Config;
use strict;
-use integer;
use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK );
$VERSION = '1.18_01';
@@ -29,13 +28,8 @@ use constant SECS_PER_MINUTE => 60;
use constant SECS_PER_HOUR => 3600;
use constant SECS_PER_DAY => 86400;
-my $MaxInt = ( ( 1 << ( 8 * $Config{ivsize} - 2 ) ) - 1 ) * 2 + 1;
-my $MaxDay = int( ( $MaxInt - ( SECS_PER_DAY / 2 ) ) / SECS_PER_DAY ) - 1;
-
-if ( $^O eq 'MacOS' ) {
- # time_t is unsigned...
- $MaxInt = ( 1 << ( 8 * $Config{ivsize} ) ) - 1;
-}
+# localtime()'s limit is the year 2**31
+my $MaxDay = 365 * (2**31);
# Determine the EPOC day for this machine
my $Epoc = 0;
@@ -65,13 +59,13 @@ sub _daygm {
return $_[3] + (
$Cheat{ pack( 'ss', @_[ 4, 5 ] ) } ||= do {
my $month = ( $_[4] + 10 ) % 12;
- my $year = $_[5] + 1900 - $month / 10;
+ my $year = $_[5] + 1900 - int($month / 10);
( ( 365 * $year )
- + ( $year / 4 )
- - ( $year / 100 )
- + ( $year / 400 )
- + ( ( ( $month * 306 ) + 5 ) / 10 )
+ + int( $year / 4 )
+ - int( $year / 100 )
+ + int( $year / 400 )
+ + int( ( ( $month * 306 ) + 5 ) / 10 )
)
- $Epoc;
}
diff --git a/lib/Time/Local.t b/lib/Time/Local.t
index 22138cfc0e..ef32b40405 100755
--- a/lib/Time/Local.t
+++ b/lib/Time/Local.t
@@ -25,10 +25,10 @@ my @time =
# leap day
[2020, 2, 29, 12, 59, 59],
[2030, 7, 4, 17, 07, 06],
-# The following test fails on a surprising number of systems
-# so it is commented out. The end of the Epoch for a 32-bit signed
-# implementation of time_t should be Jan 19, 2038 03:14:07 UTC.
-# [2038, 1, 17, 23, 59, 59], # last full day in any tz
+ [2038, 1, 17, 23, 59, 59], # last full day in any tz
+
+ # more than 2**31 time_t
+ [2258, 8, 11, 1, 49, 17],
);
my @bad_time =
@@ -88,7 +88,7 @@ for (@time, @neg_time) {
$year -= 1900;
$mon--;
- SKIP: {
+ SKIP: {
skip '1970 test on VOS fails.', 12
if $^O eq 'vos' && $year == 70;
skip 'this platform does not support negative epochs.', 12
@@ -107,20 +107,21 @@ for (@time, @neg_time) {
is($M, $mon, "timelocal month for @$_");
is($Y, $year, "timelocal year for @$_");
}
+ }
- {
- my $year_in = $year < 70 ? $year + 1900 : $year;
- my $time = timegm($sec,$min,$hour,$mday,$mon,$year_in);
+ # Perl has its own gmtime()
+ {
+ my $year_in = $year < 70 ? $year + 1900 : $year;
+ my $time = timegm($sec,$min,$hour,$mday,$mon,$year_in);
- my($s,$m,$h,$D,$M,$Y) = gmtime($time);
+ my($s,$m,$h,$D,$M,$Y) = gmtime($time);
- is($s, $sec, "timegm second for @$_");
- is($m, $min, "timegm minute for @$_");
- is($h, $hour, "timegm hour for @$_");
- is($D, $mday, "timegm day for @$_");
- is($M, $mon, "timegm month for @$_");
- is($Y, $year, "timegm year for @$_");
- }
+ is($s, $sec, "timegm second for @$_");
+ is($m, $min, "timegm minute for @$_");
+ is($h, $hour, "timegm hour for @$_");
+ is($D, $mday, "timegm day for @$_");
+ is($M, $mon, "timegm month for @$_");
+ is($Y, $year, "timegm year for @$_");
}
}
@@ -166,11 +167,7 @@ for my $p (@years) {
"$year $string a leap year" );
}
-SKIP:
{
- skip 'this platform does not support negative epochs.', 6
- unless $neg_epoch_ok;
-
eval { timegm(0,0,0,29,1,1900) };
like($@, qr/Day '29' out of range 1\.\.28/,
'does not accept leap day in 1900');