summaryrefslogtreecommitdiff
path: root/time64.c
diff options
context:
space:
mode:
authorMichael G. Schwern <schwern@pobox.com>2008-10-04 18:24:54 -0400
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2009-01-03 18:39:16 +0100
commit461d5a49bcaf1bdc023edb10ef9b6c0606ec0131 (patch)
treeb320c5fc7d5618b148e9437543445ba6ec23e764 /time64.c
parentb86b480f7301a8816081189c89b366a79ab9909f (diff)
downloadperl-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.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/time64.c b/time64.c
index 8d5820dfb7..21fe116030 100644
--- a/time64.c
+++ b/time64.c
@@ -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