From 86203a88aee76517c3c8862057e3315e0d479489 Mon Sep 17 00:00:00 2001 From: akr Date: Wed, 31 Mar 2004 10:27:58 +0000 Subject: * time.c (year_leap_p): new function. (timegm_noleapsecond): ditto. (search_time_t): use timegm_noleapsecond instead of mktime for first guess. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6057 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 9 +++++- time.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index b59f7ce538..0d7d6758bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Mar 31 19:06:23 2004 Tanaka Akira + + * time.c (year_leap_p): new function. + (timegm_noleapsecond): ditto. + (search_time_t): use timegm_noleapsecond instead of + mktime for first guess. + Wed Mar 31 12:04:04 2004 Nobuyoshi Nakada * lib/delegate.rb (DelegateClass): define internal methods of the @@ -10,7 +17,7 @@ Wed Mar 31 12:04:04 2004 Nobuyoshi Nakada Tue Mar 30 20:25:34 2004 Tanaka Akira * time.c (search_time_t): limit guess range by mktime if it is - available. + available. [ruby-dev:23274] Sun Mar 28 14:16:59 2004 Minero Aoki diff --git a/time.c b/time.c index a81c3bb789..2dec206009 100644 --- a/time.c +++ b/time.c @@ -398,6 +398,71 @@ static VALUE time_gmtime _((VALUE)); static VALUE time_localtime _((VALUE)); static VALUE time_get_tm _((VALUE, int)); +static int +leap_year_p(y) + long y; +{ + return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0); +} + +#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d)) + +static time_t +timegm_noleapsecond(tm) + struct tm *tm; +{ + static int common_year_yday_offset[] = { + -1, + -1 + 31, + -1 + 31 + 28, + -1 + 31 + 28 + 31, + -1 + 31 + 28 + 31 + 30, + -1 + 31 + 28 + 31 + 30 + 31, + -1 + 31 + 28 + 31 + 30 + 31 + 30, + -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31, + -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, + -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + /* 1 2 3 4 5 6 7 8 9 10 11 */ + }; + static int leap_year_yday_offset[] = { + -1, + -1 + 31, + -1 + 31 + 29, + -1 + 31 + 29 + 31, + -1 + 31 + 29 + 31 + 30, + -1 + 31 + 29 + 31 + 30 + 31, + -1 + 31 + 29 + 31 + 30 + 31 + 30, + -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31, + -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31, + -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + /* 1 2 3 4 5 6 7 8 9 10 11 */ + }; + + long tm_year = tm->tm_year; + int tm_yday = tm->tm_mday; + if (leap_year_p(tm_year + 1900)) + tm_yday += leap_year_yday_offset[tm->tm_mon]; + else + tm_yday += common_year_yday_offset[tm->tm_mon]; + + /* + * `Seconds Since the Epoch' in SUSv3: + * tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 + + * (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 - + * ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400 + */ + return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 + + (time_t)(tm_yday + + (tm_year-70)*365 + + DIV(tm_year-69,4) - + DIV(tm_year-1,100) + + DIV(tm_year+299,400))*86400; +} + static int tmcmp(a, b) struct tm *a; @@ -440,14 +505,29 @@ search_time_t(tptr, utc_p) (1UL << (8 * sizeof(time_t) - 1)) - 1 : ~(time_t)0; -#if defined(HAVE_MKTIME) - if ((guess = mktime(tptr)) != -1) { - if (guess_lo < guess - 24 * 60 * 60) - guess_lo = guess - 24 * 60 * 60; - if (guess + 24 * 60 * 60 < guess_hi) - guess_hi = guess + 24 * 60 * 60; + guess = timegm_noleapsecond(tptr); + tm = (utc_p ? gmtime : localtime)(&guess); + if (tm) { + d = tmcmp(tptr, tm); + if (d == 0) return guess; + if (d < 0) { + guess_hi = guess; + guess -= 24 * 60 * 60; + } + else { + guess_lo = guess; + guess += 24 * 60 * 60; + } + if (guess_lo < guess && guess < guess_hi && + (tm = (utc_p ? gmtime : localtime)(&guess)) != NULL) { + d = tmcmp(tptr, tm); + if (d == 0) return guess; + if (d < 0) + guess_hi = guess; + else + guess_lo = guess; + } } -#endif tm = (utc_p ? gmtime : localtime)(&guess_lo); if (!tm) goto error; -- cgit v1.2.3