diff options
author | Michael G. Schwern <schwern@pobox.com> | 2008-10-04 18:24:54 -0400 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2009-01-03 18:39:16 +0100 |
commit | 461d5a49bcaf1bdc023edb10ef9b6c0606ec0131 (patch) | |
tree | b320c5fc7d5618b148e9437543445ba6ec23e764 /time64.c | |
parent | b86b480f7301a8816081189c89b366a79ab9909f (diff) | |
download | perl-461d5a49bcaf1bdc023edb10ef9b6c0606ec0131.tar.gz |
Update from y2038.
Add trace code.
Fix implied negative time in localtie64_r(). This fixes Windows.
Put in some more tests around small negative and positive times to
try and catch the above.
Explain the loss of accuracy due to use of doubles in perlport.
Diffstat (limited to 'time64.c')
-rw-r--r-- | time64.c | 41 |
1 files changed, 27 insertions, 14 deletions
@@ -108,11 +108,18 @@ static const int dow_year_start[SOLAR_CYCLE_LENGTH] = { # define SHOULD_USE_SYSTEM_GMTIME(a) (0) #endif +#ifdef TIME_64_DEBUG +# define TRACE(format, ...) (fprintf(stderr, format, __VA_ARGS__)) +# define TRACE_NO_VARS(format) (fprintf(stderr, format)) +#else +# define TRACE(format, ...) ((void)0) +# define TRACE_NO_VARS(format) ((void)0) +#endif static int is_exception_century(Year year) { int is_exception = ((year % 100 == 0) && !(year % 400 == 0)); - /* printf("is_exception_century: %s\n", is_exception ? "yes" : "no"); */ + TRACE("# is_exception_century: %s\n", is_exception ? "yes" : "no"); return(is_exception); } @@ -201,10 +208,8 @@ static Year cycle_offset(Year year) exceptions = year_diff / 100; exceptions -= year_diff / 400; - /* - fprintf(stderr, "# year: %lld, exceptions: %lld, year_diff: %lld\n", - year, exceptions, year_diff); - */ + TRACE("# year: %lld, exceptions: %lld, year_diff: %lld\n", + year, exceptions, year_diff); return exceptions * 16; } @@ -249,10 +254,8 @@ static int safe_year(Year year) assert(safe_year <= 2037 && safe_year >= 2010); - /* - printf("year: %d, year_cycle: %d, safe_year: %d\n", - year, year_cycle, safe_year); - */ + TRACE("# year: %lld, year_cycle: %lld, safe_year: %d\n", + year, year_cycle, safe_year); return safe_year; } @@ -413,7 +416,7 @@ struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p) if (m >= 0) { /* Gregorian cycles, this is huge optimization for distant times */ - cycles = m / (Time64_T) days_in_gregorian_cycle; + cycles = (int)(m / (Time64_T) days_in_gregorian_cycle); if( cycles ) { m -= (cycles * (Time64_T) days_in_gregorian_cycle); year += (cycles * years_in_gregorian_cycle); @@ -437,7 +440,7 @@ struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p) year--; /* Gregorian cycles */ - cycles = (m / (Time64_T) days_in_gregorian_cycle) + 1; + cycles = (int)((m / (Time64_T) days_in_gregorian_cycle) + 1); if( cycles ) { m -= (cycles * (Time64_T) days_in_gregorian_cycle); year += (cycles * years_in_gregorian_cycle); @@ -497,6 +500,8 @@ struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm) if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) { safe_time = *time; + TRACE("Using system localtime for %lld\n", *time); + LOCALTIME_R(&safe_time, &safe_date); copy_tm_to_TM(&safe_date, local_tm); @@ -505,26 +510,34 @@ struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm) return local_tm; } - if( gmtime64_r(time, &gm_tm) == NULL ) + if( gmtime64_r(time, &gm_tm) == NULL ) { + TRACE("gmtime64_r returned null for %lld\n", *time); return NULL; + } orig_year = gm_tm.tm_year; if (gm_tm.tm_year > (2037 - 1900) || - gm_tm.tm_year < (1902 - 1900) + gm_tm.tm_year < (1970 - 1900) ) { + TRACE("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year); gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900; } safe_time = timegm64(&gm_tm); - if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) + if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) { + TRACE("localtime_r(%d) returned NULL\n", (int)safe_time); return NULL; + } copy_tm_to_TM(&safe_date, local_tm); local_tm->tm_year = orig_year; if( local_tm->tm_year != orig_year ) { + TRACE("tm_year overflow: tm_year %lld, orig_year %lld\n", + (Year)local_tm->tm_year, (Year)orig_year); + #ifdef EOVERFLOW errno = EOVERFLOW; #endif |