Rcpp Version 0.9.10
Date.cpp
Go to the documentation of this file.
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002 //
00003 // Date.h: Rcpp R/C++ interface class library -- Date type
00004 //
00005 // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois
00006 //
00007 //    The mktime00() as well as the gmtime_() replacement function are
00008 //    Copyright (C) 2000 - 2010  The R Development Core Team.
00009 // 
00010 //    gmtime_() etc are from the public domain timezone code dated 
00011 //    1996-06-05 by Arthur David Olson.
00012 //
00013 // This file is part of Rcpp.
00014 //
00015 // Rcpp is free software: you can redistribute it and/or modify it
00016 // under the terms of the GNU General Public License as published by
00017 // the Free Software Foundation, either version 2 of the License, or
00018 // (at your option) any later version.
00019 //
00020 // Rcpp is distributed in the hope that it will be useful, but
00021 // WITHOUT ANY WARRANTY; without even the implied warranty of
00022 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 // GNU General Public License for more details.
00024 //
00025 // You should have received a copy of the GNU General Public License
00026 // along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
00027 
00028 #include <Rcpp/Date.h>
00029 #include <Rcpp/Function.h>
00030 #include <time.h>               // for gmtime
00031 
00032 namespace Rcpp {
00033 
00034     static struct tm * gmtime_(const time_t * const timep);     // see below
00035 
00036 
00037     const unsigned int Date::QLtoJan1970Offset = 25569;         // Offset between R / Unix epoch date and the QL base date
00038     const unsigned int Date::baseYear = 1900;                   // because we hate macros
00039 
00040     Date::Date() {
00041         m_d = 0; 
00042         update_tm();
00043     }
00044 
00045     Date::Date(SEXP d) {
00046         m_d = Rcpp::as<int>(d); 
00047         update_tm();
00048     }
00049 
00050     Date::Date(const int &dt) {
00051         m_d = dt;
00052         update_tm();
00053     }
00054 
00055     Date::Date(const std::string &s, const std::string &fmt) {
00056         Rcpp::Function strptime("strptime");    // we cheat and call strptime() from R
00057         Rcpp::Function asDate("as.Date");       // and we need to convert to Date
00058         m_d = Rcpp::as<int>(asDate(strptime(s, fmt, "UTC")));
00059         update_tm();
00060     }
00061 
00062     Date::Date(const unsigned int &mon, const unsigned int &day, const unsigned int &year) {
00063 
00064         m_tm.tm_sec = m_tm.tm_min = m_tm.tm_hour = m_tm.tm_isdst = 0;
00065 
00066         // allow for ISO-notation case (yyyy, mm, dd) which we prefer over (mm, dd, year)
00067         if (mon >= baseYear && day <= 12 && year <= 31) {
00068             m_tm.tm_year = mon - baseYear;
00069             m_tm.tm_mon  = day - 1;     // range 0 to 11
00070             m_tm.tm_mday = year;
00071         } else {
00072             m_tm.tm_mday  = day;
00073             m_tm.tm_mon   = mon - 1;    // range 0 to 11
00074             m_tm.tm_year  = year - baseYear;
00075         }
00076         double tmp = mktime00(m_tm);    // use mktime() replacement borrowed from R
00077         m_tm.tm_year += baseYear;       // we'd rather keep it as a normal year
00078         m_d = tmp/(24*60*60);
00079     }
00080 
00081     Date::Date(const Date &copy) {
00082         m_d = copy.m_d;
00083         m_tm = copy.m_tm;
00084     }
00085 
00086     Date & Date::operator=(const Date & newdate) {
00087         if (this != &newdate) {
00088             m_d = newdate.m_d;
00089             m_tm = newdate.m_tm;
00090         }
00091         return *this;
00092     }
00093 
00094     void Date::update_tm() {
00095         time_t t = 24*60*60 * m_d;      // days since epoch to seconds since epoch
00096         //m_tm = *gmtime(&t);           // this may need a Windows fix, re-check R's datetime.c
00097         m_tm = *gmtime_(&t);
00098     }
00099 
00100     // Taken from R's src/main/datetime.c and made a member function called with C++ reference
00101     /* Substitute for mktime -- no checking, always in GMT */
00102     double Date::mktime00(struct tm &tm) const {
00103 
00104         static const int days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00105 
00106         #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
00107         #define days_in_year(year) (isleap(year) ? 366 : 365)
00108 
00109         int day = 0;
00110         int i, year, year0;
00111         double excess = 0.0;
00112 
00113         day = tm.tm_mday - 1;
00114         year0 = baseYear + tm.tm_year;
00115         /* safety check for unbounded loops */
00116         if (year0 > 3000) {
00117             excess = (int)(year0/2000) - 1;
00118             year0 -= excess * 2000;
00119         } else if (year0 < 0) {
00120             excess = -1 - (int)(-year0/2000);
00121             year0 -= excess * 2000;
00122         }
00123 
00124         for(i = 0; i < tm.tm_mon; i++) day += days_in_month[i];
00125         if (tm.tm_mon > 1 && isleap(year0)) day++;
00126         tm.tm_yday = day;
00127 
00128         if (year0 > 1970) {
00129             for (year = 1970; year < year0; year++)
00130                 day += days_in_year(year);
00131         } else if (year0 < 1970) {
00132             for (year = 1969; year >= year0; year--)
00133                 day -= days_in_year(year);
00134         }
00135 
00136         /* weekday: Epoch day was a Thursday */
00137         if ((tm.tm_wday = (day + 4) % 7) < 0) tm.tm_wday += 7;
00138         
00139         return tm.tm_sec + (tm.tm_min * 60) + (tm.tm_hour * 3600)
00140             + (day + excess * 730485) * 86400.0;
00141     }
00142     #undef isleap
00143     #undef days_in_year 
00144 
00145     Date operator+(const Date &date, int offset) {
00146         Date newdate(date.m_d);
00147         newdate.m_d += offset;
00148         time_t t = 24*60*60 * newdate.m_d;      // days since epoch to seconds since epo
00149         //newdate.m_tm = *gmtime(&t);           // this may need a Windows fix, re-check R's datetime.c
00150         newdate.m_tm = *gmtime_(&t);
00151         return newdate;
00152     }
00153 
00154     int   operator-(const Date& d1, const Date& d2) { return d2.m_d - d1.m_d; }
00155     bool  operator<(const Date &d1, const Date& d2) { return d1.m_d < d2.m_d; }
00156     bool  operator>(const Date &d1, const Date& d2) { return d1.m_d > d2.m_d; }
00157     bool  operator==(const Date &d1, const Date& d2) { return d1.m_d == d2.m_d; }
00158     bool  operator>=(const Date &d1, const Date& d2) { return d1.m_d >= d2.m_d; }
00159     bool  operator<=(const Date &d1, const Date& d2) { return d1.m_d <= d2.m_d; }
00160     bool  operator!=(const Date &d1, const Date& d2) { return d1.m_d != d2.m_d; }
00161 
00162     template <> SEXP wrap(const Date &date) {
00163         return internal::new_date_object( date.getDate() ) ;
00164     }
00165 
00166 
00167 
00168 #include "sys/types.h"  /* for time_t */
00169 #include "string.h"
00170 #include "limits.h"     /* for CHAR_BIT et al. */
00171 
00172 #define  _NO_OLDNAMES   /* avoid tznames */
00173 #include "time.h"
00174 #undef _NO_OLDNAMES
00175 
00176 #include <errno.h>
00177 #ifndef EOVERFLOW
00178 # define EOVERFLOW 79
00179 #endif
00180 
00181 #include "stdlib.h"
00182 #include "stdint.h"
00183 #include "stdio.h"
00184 #include "fcntl.h"
00185 #include "float.h"      /* for FLT_MAX and DBL_MAX */
00186 
00187 #include <unistd.h>             // solaris needs this for read() and close()
00188 
00189 
00190 /* merged from private.h */
00191 #define TYPE_BIT(type)  (sizeof (type) * CHAR_BIT)
00192 #define TYPE_SIGNED(type) (((type) -1) < 0)
00193 #define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
00194 #define GRANDPARENTED   "Local time zone must be set--see zic manual page"
00195 #define YEARSPERREPEAT   400    /* years before a Gregorian repeat */
00196 #define AVGSECSPERYEAR   31556952L
00197 #define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
00198 #define SECSPERREPEAT_BITS  34  /* ceil(log2(SECSPERREPEAT)) */
00199 #define is_digit(c) ((unsigned)(c) - '0' <= 9)
00200 #define INITIALIZE(x) (x = 0)
00201 
00202     //#include "tzfile.h"
00203     // BEGIN ------------------------------------------------------------------------------------------ tzfile.h
00204 #ifndef TZFILE_H
00205 
00206 #define TZFILE_H
00207 
00208 /*
00209 ** This file is in the public domain, so clarified as of
00210 ** 1996-06-05 by Arthur David Olson.
00211 */
00212 
00213 /*
00214 ** This header is for use ONLY with the time conversion code.
00215 ** There is no guarantee that it will remain unchanged,
00216 ** or that it will remain at all.
00217 ** Do NOT copy it to any system include directory.
00218 ** Thank you!
00219 */
00220 
00221 /*
00222 ** Information about time zone files.
00223 */
00224 
00225 #ifndef TZDIR
00226 #define TZDIR   "/usr/local/etc/zoneinfo" /* Time zone object file directory */
00227 #endif /* !defined TZDIR */
00228 
00229 #ifndef TZDEFAULT
00230 #define TZDEFAULT       "localtime"
00231 #endif /* !defined TZDEFAULT */
00232 
00233 #ifndef TZDEFRULES
00234 #define TZDEFRULES      "America/New_York"
00235 #endif /* !defined TZDEFRULES */
00236 
00237 /*
00238 ** Each file begins with. . .
00239 */
00240 
00241 #define TZ_MAGIC        "TZif"
00242 
00243 struct tzhead {
00244         char    tzh_magic[4];           /* TZ_MAGIC */
00245         char    tzh_version[1];         /* '\0' or '2' as of 2005 */
00246         char    tzh_reserved[15];       /* reserved--must be zero */
00247         char    tzh_ttisgmtcnt[4];      /* coded number of trans. time flags */
00248         char    tzh_ttisstdcnt[4];      /* coded number of trans. time flags */
00249         char    tzh_leapcnt[4];         /* coded number of leap seconds */
00250         char    tzh_timecnt[4];         /* coded number of transition times */
00251         char    tzh_typecnt[4];         /* coded number of local time types */
00252         char    tzh_charcnt[4];         /* coded number of abbr. chars */
00253 };
00254 
00255 /*
00256 ** . . .followed by. . .
00257 **
00258 **      tzh_timecnt (char [4])s         coded transition times a la time(2)
00259 **      tzh_timecnt (unsigned char)s    types of local time starting at above
00260 **      tzh_typecnt repetitions of
00261 **              one (char [4])          coded UTC offset in seconds
00262 **              one (unsigned char)     used to set tm_isdst
00263 **              one (unsigned char)     that's an abbreviation list index
00264 **      tzh_charcnt (char)s             '\0'-terminated zone abbreviations
00265 **      tzh_leapcnt repetitions of
00266 **              one (char [4])          coded leap second transition times
00267 **              one (char [4])          total correction after above
00268 **      tzh_ttisstdcnt (char)s          indexed by type; if TRUE, transition
00269 **                                      time is standard time, if FALSE,
00270 **                                      transition time is wall clock time
00271 **                                      if absent, transition times are
00272 **                                      assumed to be wall clock time
00273 **      tzh_ttisgmtcnt (char)s          indexed by type; if TRUE, transition
00274 **                                      time is UTC, if FALSE,
00275 **                                      transition time is local time
00276 **                                      if absent, transition times are
00277 **                                      assumed to be local time
00278 */
00279 
00280 /*
00281 ** If tzh_version is '2' or greater, the above is followed by a second instance
00282 ** of tzhead and a second instance of the data in which each coded transition
00283 ** time uses 8 rather than 4 chars,
00284 ** then a POSIX-TZ-environment-variable-style string for use in handling
00285 ** instants after the last transition time stored in the file
00286 ** (with nothing between the newlines if there is no POSIX representation for
00287 ** such instants).
00288 */
00289 
00290 /*
00291 ** In the current implementation, "tzset()" refuses to deal with files that
00292 ** exceed any of the limits below.
00293 */
00294 
00295 #ifndef TZ_MAX_TIMES
00296 #define TZ_MAX_TIMES    1200
00297 #endif /* !defined TZ_MAX_TIMES */
00298 
00299 #ifndef TZ_MAX_TYPES
00300 #ifndef NOSOLAR
00301 #define TZ_MAX_TYPES    256 /* Limited by what (unsigned char)'s can hold */
00302 #endif /* !defined NOSOLAR */
00303 #ifdef NOSOLAR
00304 /*
00305 ** Must be at least 14 for Europe/Riga as of Jan 12 1995,
00306 ** as noted by Earl Chew.
00307 */
00308 #define TZ_MAX_TYPES    20      /* Maximum number of local time types */
00309 #endif /* !defined NOSOLAR */
00310 #endif /* !defined TZ_MAX_TYPES */
00311 
00312 #ifndef TZ_MAX_CHARS
00313 #define TZ_MAX_CHARS    50      /* Maximum number of abbreviation characters */
00314                                 /* (limited by what unsigned chars can hold) */
00315 #endif /* !defined TZ_MAX_CHARS */
00316 
00317 #ifndef TZ_MAX_LEAPS
00318 #define TZ_MAX_LEAPS    50      /* Maximum number of leap second corrections */
00319 #endif /* !defined TZ_MAX_LEAPS */
00320 
00321 #define SECSPERMIN      60
00322 #define MINSPERHOUR     60
00323 #define HOURSPERDAY     24
00324 #define DAYSPERWEEK     7
00325 #define DAYSPERNYEAR    365
00326 #define DAYSPERLYEAR    366
00327 #define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR)
00328 #define SECSPERDAY      ((long) SECSPERHOUR * HOURSPERDAY)
00329 #define MONSPERYEAR     12
00330 
00331 #define TM_SUNDAY       0
00332 #define TM_MONDAY       1
00333 #define TM_TUESDAY      2
00334 #define TM_WEDNESDAY    3
00335 #define TM_THURSDAY     4
00336 #define TM_FRIDAY       5
00337 #define TM_SATURDAY     6
00338 
00339 #define TM_JANUARY      0
00340 #define TM_FEBRUARY     1
00341 #define TM_MARCH        2
00342 #define TM_APRIL        3
00343 #define TM_MAY          4
00344 #define TM_JUNE         5
00345 #define TM_JULY         6
00346 #define TM_AUGUST       7
00347 #define TM_SEPTEMBER    8
00348 #define TM_OCTOBER      9
00349 #define TM_NOVEMBER     10
00350 #define TM_DECEMBER     11
00351 
00352 #define TM_YEAR_BASE    baseYear        // was: 1900, baseYear defined above
00353 
00354 #define EPOCH_YEAR      1970
00355 #define EPOCH_WDAY      TM_THURSDAY
00356 
00357 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
00358 
00359 /*
00360 ** Since everything in isleap is modulo 400 (or a factor of 400), we know that
00361 **      isleap(y) == isleap(y % 400)
00362 ** and so
00363 **      isleap(a + b) == isleap((a + b) % 400)
00364 ** or
00365 **      isleap(a + b) == isleap(a % 400 + b % 400)
00366 ** This is true even if % means modulo rather than Fortran remainder
00367 ** (which is allowed by C89 but not C99).
00368 ** We use this to avoid addition overflow problems.
00369 */
00370 
00371 #define isleap_sum(a, b)        isleap((a) % 400 + (b) % 400)
00372 
00373 #endif /* !defined TZFILE_H */
00374 
00375     // -------------------------------------------------------------------------------------- END tzfile.h
00376 
00377 #ifdef O_BINARY
00378 #define OPEN_MODE       (O_RDONLY | O_BINARY)
00379 #endif /* defined O_BINARY */
00380 #ifndef O_BINARY
00381 #define OPEN_MODE       O_RDONLY
00382 #endif /* !defined O_BINARY */
00383 
00384     static const char   gmt[] = "GMT";
00385 
00386     /*
00387     ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
00388     ** We default to US rules as of 1999-08-17.
00389     ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
00390     ** implementation dependent; for historical reasons, US rules are a
00391     ** common default.
00392     */
00393 #ifndef TZDEFRULESTRING
00394 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
00395 #endif /* !defined TZDEFDST */
00396 
00397 #define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
00398 
00399 #ifdef TZNAME_MAX
00400 #define MY_TZNAME_MAX   TZNAME_MAX
00401 #endif /* defined TZNAME_MAX */
00402 #ifndef TZNAME_MAX
00403 #define MY_TZNAME_MAX   255
00404 #endif /* !defined TZNAME_MAX */
00405 
00406     struct ttinfo {                             /* time type information */
00407         long            tt_gmtoff;      /* UTC offset in seconds */
00408         int             tt_isdst;       /* used to set tm_isdst */
00409         int             tt_abbrind;     /* abbreviation list index */
00410         int             tt_ttisstd;     /* TRUE if transition is std time */
00411         int             tt_ttisgmt;     /* TRUE if transition is UTC */
00412     };
00413 
00414     struct lsinfo {                             /* leap second information */
00415         time_t          ls_trans;       /* transition time */
00416         long            ls_corr;        /* correction to apply */
00417     };
00418 
00419     struct state {
00420         int             leapcnt;
00421         int             timecnt;
00422         int             typecnt;
00423         int             charcnt;
00424         int             goback;
00425         int             goahead;
00426         time_t          ats[TZ_MAX_TIMES];
00427         unsigned char   types[TZ_MAX_TIMES];
00428         struct ttinfo   ttis[TZ_MAX_TYPES];
00429         char            chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
00430                                       (2 * (MY_TZNAME_MAX + 1)))];
00431         struct lsinfo   lsis[TZ_MAX_LEAPS];
00432     };
00433 
00434     struct rule {
00435         int             r_type;         /* type of rule--see below */
00436         int             r_day;          /* day number of rule */
00437         int             r_week;         /* week number of rule */
00438         int             r_mon;          /* month number of rule */
00439         long            r_time;         /* transition time of rule */
00440     };
00441 
00442 #define JULIAN_DAY              0       /* Jn - Julian day */
00443 #define DAY_OF_YEAR             1       /* n - day of year */
00444 #define MONTH_NTH_DAY_OF_WEEK   2       /* Mm.n.d - month, week, day of week */
00445 
00446     static const int mon_lengths[2][MONSPERYEAR] = {
00447         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00448         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00449     };
00450 
00451     static const int year_lengths[2] = {
00452         DAYSPERNYEAR, DAYSPERLYEAR
00453     };
00454 
00455     static int          gmt_is_set;
00456 
00457     //static struct state       lclmem;
00458     static struct state gmtmem;
00459     //#define lclptr            (&lclmem)
00460 #define gmtptr          (&gmtmem)
00461 
00462     static struct tm  tm;
00463 
00464     //extern const char *getTZinfo(void);
00465 
00466     static int          tzparse(const char * name, struct state * sp, int lastditch);
00467     static int          typesequiv(const struct state * sp, int a, int b);
00468     static const char * getsecs(const char * strp, long * secsp);
00469     static const char * getnum(const char * strp, int * const nump, const int min, const int max);
00470     static const char * getrule(const char * strp, struct rule * const rulep);
00471     static time_t transtime(const time_t janfirst, const int year, const struct rule * const rulep, const long offset);
00472     static struct tm * timesub(const time_t * const timep, const long offset, const struct state * const sp, struct tm * const tmp);
00473     static int leaps_thru_end_of(const int y);
00474 
00475     static int increment_overflow(int * number, int delta) {
00476         int     number0;
00477 
00478         number0 = *number;
00479         *number += delta;
00480         return (*number < number0) != (delta < 0);
00481     }
00482 
00483     static long detzcode(const char * const codep) {
00484         long result;
00485         int     i;
00486 
00487         result = (codep[0] & 0x80) ? ~0L : 0;
00488         for (i = 0; i < 4; ++i)
00489             result = (result << 8) | (codep[i] & 0xff);
00490         return result;
00491     }
00492 
00493     static time_t detzcode64(const char * const codep) {
00494         time_t result;
00495         int     i;
00496 
00497         result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
00498         for (i = 0; i < 8; ++i)
00499             result = result * 256 + (codep[i] & 0xff);
00500         return result;
00501     }
00502 
00503     static int differ_by_repeat(const time_t t1, const time_t t0) {
00504         if (TYPE_INTEGRAL(time_t) &&
00505             TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
00506             return 0;
00507         /* R change */
00508         return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT;
00509     }
00510 
00511     static const char * getzname(const char * strp) {
00512         char c;
00513 
00514         while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00515                c != '+')
00516             ++strp;
00517         return strp;
00518     }
00519 
00520     static const char * getqzname(const char *strp, const int delim) {
00521         int     c;
00522 
00523         while ((c = *strp) != '\0' && c != delim)
00524             ++strp;
00525         return strp;
00526     }
00527 
00528     static const char * getoffset(const char * strp, long * const offsetp) {
00529         int     neg = 0;
00530 
00531         if (*strp == '-') {
00532             neg = 1;
00533             ++strp;
00534         } else if (*strp == '+')
00535             ++strp;
00536         strp = getsecs(strp, offsetp);
00537         if (strp == NULL)
00538             return NULL;                /* illegal time */
00539         if (neg)
00540             *offsetp = -*offsetp;
00541         return strp;
00542     }
00543 
00544     static const char * getsecs( const char * strp, long * const secsp) {
00545         int     num;
00546 
00547         /*
00548         ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
00549         ** "M10.4.6/26", which does not conform to Posix,
00550         ** but which specifies the equivalent of
00551         ** ``02:00 on the first Sunday on or after 23 Oct''.
00552         */
00553         strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00554         if (strp == NULL)
00555             return NULL;
00556         *secsp = num * (long) SECSPERHOUR;
00557         if (*strp == ':') {
00558             ++strp;
00559             strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00560             if (strp == NULL)
00561                 return NULL;
00562             *secsp += num * SECSPERMIN;
00563             if (*strp == ':') {
00564                 ++strp;
00565                 /* `SECSPERMIN' allows for leap seconds. */
00566                 strp = getnum(strp, &num, 0, SECSPERMIN);
00567                 if (strp == NULL)
00568                     return NULL;
00569                 *secsp += num;
00570             }
00571         }
00572         return strp;
00573     }
00574 
00575     static const char * getnum(const char * strp, int * const nump, const int min, const int max) {
00576         char c;
00577         int     num;
00578 
00579         if (strp == NULL || !is_digit(c = *strp))
00580             return NULL;
00581         num = 0;
00582         do {
00583             num = num * 10 + (c - '0');
00584             if (num > max)
00585                 return NULL;    /* illegal value */
00586             c = *++strp;
00587         } while (is_digit(c));
00588         if (num < min)
00589             return NULL;                /* illegal value */
00590         *nump = num;
00591         return strp;
00592     }
00593 
00594     static const char * getrule(const char * strp, struct rule * const rulep) {
00595         if (*strp == 'J') {
00596             /*
00597             ** Julian day.
00598             */
00599             rulep->r_type = JULIAN_DAY;
00600             ++strp;
00601             strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00602         } else if (*strp == 'M') {
00603             /*
00604             ** Month, week, day.
00605             */
00606             rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00607             ++strp;
00608             strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00609             if (strp == NULL)
00610                 return NULL;
00611             if (*strp++ != '.')
00612                 return NULL;
00613             strp = getnum(strp, &rulep->r_week, 1, 5);
00614             if (strp == NULL)
00615                 return NULL;
00616             if (*strp++ != '.')
00617                 return NULL;
00618             strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00619         } else if (is_digit(*strp)) {
00620             /*
00621             ** Day of year.
00622             */
00623             rulep->r_type = DAY_OF_YEAR;
00624             strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00625         } else  return NULL;            /* invalid format */
00626         if (strp == NULL)
00627             return NULL;
00628         if (*strp == '/') {
00629             /*
00630             ** Time specified.
00631             */
00632             ++strp;
00633             strp = getsecs(strp, &rulep->r_time);
00634         } else  rulep->r_time = 2 * SECSPERHOUR;        /* default = 2:00:00 */
00635         return strp;
00636     }
00637 
00638     static int tzload(const char * name, struct state * const sp, const int doextend) {
00639         const char * p;
00640         int      i;
00641         int      fid;
00642         int      stored;
00643         int      nread;
00644         union {
00645             struct tzhead  tzhead;
00646             char  buf[2 * sizeof(struct tzhead) + 
00647                       2 * sizeof *sp + 4 * TZ_MAX_TIMES];
00648         } u;
00649 
00650         sp->goback = sp->goahead = FALSE;
00651         /* if (name == NULL && (name = TZDEFAULT) == NULL) return -1; */
00652         if (name == NULL) {
00653             // edd 06 Jul 2010  let's do without getTZinfo()
00654             //name = getTZinfo();
00655             //if( strcmp(name, "unknown") == 0 ) name = TZDEFAULT;
00656             name = TZDEFAULT;
00657         }
00658         
00659         {
00660             int  doaccess;
00661             /*
00662             ** Section 4.9.1 of the C standard says that
00663             ** "FILENAME_MAX expands to an integral constant expression
00664             ** that is the size needed for an array of char large enough
00665             ** to hold the longest file name string that the implementation
00666             ** guarantees can be opened."
00667             */
00668             char fullname[FILENAME_MAX + 1];
00669             // edd 08 Jul 2010 not currently needed  const char *sname = name;
00670 
00671             if (name[0] == ':')
00672                 ++name;
00673             doaccess = name[0] == '/';
00674             if (!doaccess) {
00675                 char buf[1000];
00676                 p = getenv("TZDIR");
00677                 if (p == NULL) {
00678                     snprintf(buf, 1000, "%s/share/zoneinfo", 
00679                              getenv("R_HOME"));
00680                     buf[999] = '\0';
00681                     p = buf;
00682                 }
00683                 /* if ((p = TZDIR) == NULL) return -1; */
00684                 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
00685                     return -1;
00686                 (void) strcpy(fullname, p);
00687                 (void) strcat(fullname, "/");
00688                 (void) strcat(fullname, name);
00689                 /*
00690                 ** Set doaccess if '.' (as in "../") shows up in name.
00691                 */
00692                 if (strchr(name, '.') != NULL) doaccess = TRUE;
00693                 name = fullname;
00694             }
00695             // edd 16 Jul 2010  comment out whole block
00696             //if (doaccess && access(name, R_OK) != 0) {
00697                 // edd 08 Jul 2010  we use this without TZ for dates only 
00698                 //                  so no need to warn
00699                 //Rf_warning("unknown timezone '%s'", sname);
00700                 //return -1;
00701             //}
00702             if ((fid = open(name, OPEN_MODE)) == -1) {
00703                 // edd 08 Jul 2010  we use this without TZ for dates only 
00704                 //                  so no need to warn
00705                 //Rf_warning("unknown timezone '%s'", sname);
00706                 return -1;
00707             }
00708                 
00709         }
00710         nread = read(fid, u.buf, sizeof u.buf);
00711         if (close(fid) < 0 || nread <= 0)
00712             return -1;
00713         for (stored = 4; stored <= 8; stored *= 2) {
00714             int ttisstdcnt;
00715             int ttisgmtcnt;
00716 
00717             ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
00718             ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
00719             sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
00720             sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
00721             sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
00722             sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
00723             p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
00724             if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00725                 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00726                 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00727                 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00728                 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00729                 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00730                 return -1;
00731             if (nread - (p - u.buf) <
00732                 sp->timecnt * stored +    /* ats */
00733                 sp->timecnt +             /* types */
00734                 sp->typecnt * 6 +                 /* ttinfos */
00735                 sp->charcnt +             /* chars */
00736                 sp->leapcnt * (stored + 4) +  /* lsinfos */
00737                 ttisstdcnt +              /* ttisstds */
00738                 ttisgmtcnt)                       /* ttisgmts */
00739                 return -1;
00740             for (i = 0; i < sp->timecnt; ++i) {
00741                 sp->ats[i] = (stored == 4) ? detzcode(p) : detzcode64(p);
00742                 p += stored;
00743             }
00744             for (i = 0; i < sp->timecnt; ++i) {
00745                 sp->types[i] = (unsigned char) *p++;
00746                 if (sp->types[i] >= sp->typecnt)
00747                     return -1;
00748             }
00749             for (i = 0; i < sp->typecnt; ++i) {
00750                 struct ttinfo * ttisp;
00751 
00752                 ttisp = &sp->ttis[i];
00753                 ttisp->tt_gmtoff = detzcode(p);
00754                 p += 4;
00755                 ttisp->tt_isdst = (unsigned char) *p++;
00756                 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00757                     return -1;
00758                 ttisp->tt_abbrind = (unsigned char) *p++;
00759                 if (ttisp->tt_abbrind < 0 ||
00760                     ttisp->tt_abbrind > sp->charcnt)
00761                     return -1;
00762             }
00763             for (i = 0; i < sp->charcnt; ++i)
00764                 sp->chars[i] = *p++;
00765             sp->chars[i] = '\0';        /* ensure '\0' at end */
00766             for (i = 0; i < sp->leapcnt; ++i) {
00767                 struct lsinfo * lsisp;
00768 
00769                 lsisp = &sp->lsis[i];
00770                 lsisp->ls_trans = (stored == 4) ? detzcode(p) : detzcode64(p);
00771                 p += stored;
00772                 lsisp->ls_corr = detzcode(p);
00773                 p += 4;
00774             }
00775             for (i = 0; i < sp->typecnt; ++i) {
00776                 struct ttinfo * ttisp;
00777 
00778                 ttisp = &sp->ttis[i];
00779                 if (ttisstdcnt == 0)
00780                     ttisp->tt_ttisstd = FALSE;
00781                 else {
00782                     ttisp->tt_ttisstd = *p++;
00783                     if (ttisp->tt_ttisstd != TRUE && ttisp->tt_ttisstd != FALSE)
00784                         return -1;
00785                 }
00786             }
00787             for (i = 0; i < sp->typecnt; ++i) {
00788                 struct ttinfo * ttisp;
00789 
00790                 ttisp = &sp->ttis[i];
00791                 if (ttisgmtcnt == 0)
00792                     ttisp->tt_ttisgmt = FALSE;
00793                 else {
00794                     ttisp->tt_ttisgmt = *p++;
00795                     if (ttisp->tt_ttisgmt != TRUE && ttisp->tt_ttisgmt != FALSE)
00796                         return -1;
00797                 }
00798             }
00799             /*
00800             ** Out-of-sort ats should mean we're running on a
00801             ** signed time_t system but using a data file with
00802             ** unsigned values (or vice versa).
00803             */
00804             for (i = 0; i < sp->timecnt - 2; ++i)
00805                 if (sp->ats[i] > sp->ats[i + 1]) {
00806                     ++i;
00807                     if (TYPE_SIGNED(time_t)) {
00808                         /*
00809                         ** Ignore the end (easy).
00810                         */
00811                         sp->timecnt = i;
00812                     } else {
00813                         /*
00814                         ** Ignore the beginning (harder).
00815                         */
00816                         int     j;
00817 
00818                         for (j = 0; j + i < sp->timecnt; ++j) {
00819                             sp->ats[j] = sp->ats[j + i];
00820                             sp->types[j] = sp->types[j + i];
00821                         }
00822                         sp->timecnt = j;
00823                     }
00824                     break;
00825                 }
00826             /*
00827             ** If this is an old file, we're done.
00828             */
00829             if (u.tzhead.tzh_version[0] == '\0')
00830                 break;
00831             nread -= p - u.buf;
00832             for (i = 0; i < nread; ++i)
00833                 u.buf[i] = p[i];
00834             /*
00835             ** If this is a narrow integer time_t system, we're done.
00836             */
00837             if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
00838                 break;
00839         }
00840         if (doextend && nread > 2 &&
00841             u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
00842             sp->typecnt + 2 <= TZ_MAX_TYPES) {
00843             struct state ts;
00844             int result;
00845 
00846             u.buf[nread - 1] = '\0';
00847             result = tzparse(&u.buf[1], &ts, FALSE);
00848             if (result == 0 && ts.typecnt == 2 &&
00849                 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
00850                 for (i = 0; i < 2; ++i)
00851                     ts.ttis[i].tt_abbrind += sp->charcnt;
00852                 for (i = 0; i < ts.charcnt; ++i)
00853                     sp->chars[sp->charcnt++] = ts.chars[i];
00854                 i = 0;
00855                 while (i < ts.timecnt && ts.ats[i] <= sp->ats[sp->timecnt - 1])
00856                     ++i;
00857                 while (i < ts.timecnt &&
00858                        sp->timecnt < TZ_MAX_TIMES) {
00859                     sp->ats[sp->timecnt] = ts.ats[i];
00860                     sp->types[sp->timecnt] = sp->typecnt + ts.types[i];
00861                     ++sp->timecnt;
00862                     ++i;
00863                 }
00864                 sp->ttis[sp->typecnt++] = ts.ttis[0];
00865                 sp->ttis[sp->typecnt++] = ts.ttis[1];
00866             }
00867         }
00868         i = 2 * YEARSPERREPEAT;
00869         sp->goback = sp->goahead = sp->timecnt > i;
00870         sp->goback = sp->goback &&
00871             typesequiv(sp, sp->types[i], sp->types[0]) &&
00872             differ_by_repeat(sp->ats[i], sp->ats[0]);
00873         sp->goahead = sp->goahead &&
00874             typesequiv(sp, sp->types[sp->timecnt - 1],
00875                        sp->types[sp->timecnt - 1 - i]) &&
00876             differ_by_repeat(sp->ats[sp->timecnt - 1],
00877                              sp->ats[sp->timecnt - 1 - i]);
00878         return 0;
00879     }
00880 
00881     static time_t transtime(const time_t janfirst, const int year, const struct rule * const rulep, const long offset) {
00882         int     leapyear;
00883         time_t value;
00884         int     i;
00885         int     d, m1, yy0, yy1, yy2, dow;
00886 
00887         INITIALIZE(value);
00888         leapyear = isleap(year);
00889         switch (rulep->r_type) {
00890 
00891         case JULIAN_DAY:
00892             /*
00893             ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
00894             ** years.
00895             ** In non-leap years, or if the day number is 59 or less, just
00896             ** add SECSPERDAY times the day number-1 to the time of
00897             ** January 1, midnight, to get the day.
00898             */
00899             value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00900             if (leapyear && rulep->r_day >= 60)
00901                 value += SECSPERDAY;
00902             break;
00903 
00904         case DAY_OF_YEAR:
00905             /*
00906             ** n - day of year.
00907             ** Just add SECSPERDAY times the day number to the time of
00908             ** January 1, midnight, to get the day.
00909             */
00910             value = janfirst + rulep->r_day * SECSPERDAY;
00911             break;
00912 
00913         case MONTH_NTH_DAY_OF_WEEK:
00914             /*
00915             ** Mm.n.d - nth "dth day" of month m.
00916             */
00917             value = janfirst;
00918             for (i = 0; i < rulep->r_mon - 1; ++i)
00919                 value += mon_lengths[leapyear][i] * SECSPERDAY;
00920 
00921             /*
00922             ** Use Zeller's Congruence to get day-of-week of first day of
00923             ** month.
00924             */
00925             m1 = (rulep->r_mon + 9) % 12 + 1;
00926             yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00927             yy1 = yy0 / 100;
00928             yy2 = yy0 % 100;
00929             dow = ((26 * m1 - 2) / 10 +
00930                    1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00931             if (dow < 0)
00932                 dow += DAYSPERWEEK;
00933 
00934             /*
00935             ** "dow" is the day-of-week of the first day of the month. Get
00936             ** the day-of-month (zero-origin) of the first "dow" day of the
00937             ** month.
00938             */
00939             d = rulep->r_day - dow;
00940             if (d < 0)
00941                 d += DAYSPERWEEK;
00942             for (i = 1; i < rulep->r_week; ++i) {
00943                 if (d + DAYSPERWEEK >=
00944                     mon_lengths[leapyear][rulep->r_mon - 1])
00945                     break;
00946                 d += DAYSPERWEEK;
00947             }
00948 
00949             /*
00950             ** "d" is the day-of-month (zero-origin) of the day we want.
00951             */
00952             value += d * SECSPERDAY;
00953             break;
00954         }
00955 
00956         /*
00957         ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
00958         ** question. To get the Epoch-relative time of the specified local
00959         ** time on that day, add the transition time and the current offset
00960         ** from UTC.
00961         */
00962         return value + rulep->r_time + offset;
00963     }
00964 
00965     static int tzparse(const char * name, struct state * const sp, const int lastditch) {
00966         const char * stdname;
00967         const char * dstname;
00968         size_t  stdlen;
00969         size_t  dstlen;
00970         long stdoffset;
00971         long dstoffset;
00972         time_t * atp;
00973         unsigned char * typep;
00974         char * cp;
00975         int     load_result;
00976 
00977         INITIALIZE(dstname);
00978         stdname = name;
00979         if (lastditch) {
00980             stdlen = strlen(name);      /* length of standard zone name */
00981             name += stdlen;
00982             if (stdlen >= sizeof sp->chars)
00983                 stdlen = (sizeof sp->chars) - 1;
00984             stdoffset = 0;
00985         } else {
00986             if (*name == '<') {
00987                 name++;
00988                 stdname = name;
00989                 name = getqzname(name, '>');
00990                 if (*name != '>')
00991                     return (-1);
00992                 stdlen = name - stdname;
00993                 name++;
00994             } else {
00995                 name = getzname(name);
00996                 stdlen = name - stdname;
00997             }
00998             if (*name == '\0')
00999                 return -1;
01000             name = getoffset(name, &stdoffset);
01001             if (name == NULL)
01002                 return -1;
01003         }
01004         load_result = tzload(TZDEFRULES, sp, FALSE);
01005         if (load_result != 0)
01006             sp->leapcnt = 0;            /* so, we're off a little */
01007         if (*name != '\0') {
01008             if (*name == '<') {
01009                 dstname = ++name;
01010                 name = getqzname(name, '>');
01011                 if (*name != '>')
01012                     return -1;
01013                 dstlen = name - dstname;
01014                 name++;
01015             } else {
01016                 dstname = name;
01017                 name = getzname(name);
01018                 dstlen = name - dstname; /* length of DST zone name */
01019             }
01020             if (*name != '\0' && *name != ',' && *name != ';') {
01021                 name = getoffset(name, &dstoffset);
01022                 if (name == NULL)
01023                     return -1;
01024             } else      dstoffset = stdoffset - SECSPERHOUR;
01025             if (*name == '\0' && load_result != 0)
01026                 name = TZDEFRULESTRING;
01027             if (*name == ',' || *name == ';') {
01028                 struct rule     start;
01029                 struct rule     end;
01030                 int     year;
01031                 time_t janfirst;
01032                 time_t starttime;
01033                 time_t endtime;
01034 
01035                 ++name;
01036                 if ((name = getrule(name, &start)) == NULL)
01037                     return -1;
01038                 if (*name++ != ',')
01039                     return -1;
01040                 if ((name = getrule(name, &end)) == NULL)
01041                     return -1;
01042                 if (*name != '\0')
01043                     return -1;
01044                 sp->typecnt = 2;        /* standard time and DST */
01045                 /*
01046                 ** Two transitions per year, from EPOCH_YEAR forward.
01047                 */
01048                 sp->ttis[0].tt_gmtoff = -dstoffset;
01049                 sp->ttis[0].tt_isdst = 1;
01050                 sp->ttis[0].tt_abbrind = stdlen + 1;
01051                 sp->ttis[1].tt_gmtoff = -stdoffset;
01052                 sp->ttis[1].tt_isdst = 0;
01053                 sp->ttis[1].tt_abbrind = 0;
01054                 atp = sp->ats;
01055                 typep = sp->types;
01056                 janfirst = 0;
01057                 sp->timecnt = 0;
01058                 for (year = EPOCH_YEAR;
01059                      sp->timecnt + 2 <= TZ_MAX_TIMES;
01060                      ++year) {
01061                     time_t newfirst;
01062 
01063                     starttime = transtime(janfirst, year, &start,
01064                                           stdoffset);
01065                     endtime = transtime(janfirst, year, &end,
01066                                         dstoffset);
01067                     if (starttime > endtime) {
01068                         *atp++ = endtime;
01069                         *typep++ = 1;   /* DST ends */
01070                         *atp++ = starttime;
01071                         *typep++ = 0;   /* DST begins */
01072                     } else {
01073                         *atp++ = starttime;
01074                         *typep++ = 0;   /* DST begins */
01075                         *atp++ = endtime;
01076                         *typep++ = 1;   /* DST ends */
01077                     }
01078                     sp->timecnt += 2;
01079                     newfirst = janfirst;
01080                     newfirst += year_lengths[isleap(year)] *
01081                         SECSPERDAY;
01082                     if (newfirst <= janfirst)
01083                         break;
01084                     janfirst = newfirst;
01085                 }
01086             } else {
01087                 long theirstdoffset;
01088                 long theirdstoffset;
01089                 long theiroffset;
01090                 int     isdst;
01091                 int     i;
01092                 int     j;
01093 
01094                 if (*name != '\0')
01095                     return -1;
01096                 /*
01097                 ** Initial values of theirstdoffset and theirdstoffset.
01098                 */
01099                 theirstdoffset = 0;
01100                 for (i = 0; i < sp->timecnt; ++i) {
01101                     j = sp->types[i];
01102                     if (!sp->ttis[j].tt_isdst) {
01103                         theirstdoffset =
01104                             -sp->ttis[j].tt_gmtoff;
01105                         break;
01106                     }
01107                 }
01108                 theirdstoffset = 0;
01109                 for (i = 0; i < sp->timecnt; ++i) {
01110                     j = sp->types[i];
01111                     if (sp->ttis[j].tt_isdst) {
01112                         theirdstoffset =
01113                             -sp->ttis[j].tt_gmtoff;
01114                         break;
01115                     }
01116                 }
01117                 /*
01118                 ** Initially we're assumed to be in standard time.
01119                 */
01120                 isdst = FALSE;
01121                 theiroffset = theirstdoffset;
01122                 /*
01123                 ** Now juggle transition times and types
01124                 ** tracking offsets as you do.
01125                 */
01126                 for (i = 0; i < sp->timecnt; ++i) {
01127                     j = sp->types[i];
01128                     sp->types[i] = sp->ttis[j].tt_isdst;
01129                     if (sp->ttis[j].tt_ttisgmt) {
01130                         /* No adjustment to transition time */
01131                     } else {
01132                         /*
01133                         ** If summer time is in effect, and the
01134                         ** transition time was not specified as
01135                         ** standard time, add the summer time
01136                         ** offset to the transition time;
01137                         ** otherwise, add the standard time
01138                         ** offset to the transition time.
01139                         */
01140                         /*
01141                         ** Transitions from DST to DDST
01142                         ** will effectively disappear since
01143                         ** POSIX provides for only one DST
01144                         ** offset.
01145                         */
01146                         if (isdst && !sp->ttis[j].tt_ttisstd) {
01147                             sp->ats[i] += dstoffset -
01148                                 theirdstoffset;
01149                         } else {
01150                             sp->ats[i] += stdoffset -
01151                                 theirstdoffset;
01152                         }
01153                     }
01154                     theiroffset = -sp->ttis[j].tt_gmtoff;
01155                     if (sp->ttis[j].tt_isdst)
01156                         theirdstoffset = theiroffset;
01157                     else        theirstdoffset = theiroffset;
01158                 }
01159                 /*
01160                 ** Finally, fill in ttis.
01161                 ** ttisstd and ttisgmt need not be handled.
01162                 */
01163                 sp->ttis[0].tt_gmtoff = -stdoffset;
01164                 sp->ttis[0].tt_isdst = FALSE;
01165                 sp->ttis[0].tt_abbrind = 0;
01166                 sp->ttis[1].tt_gmtoff = -dstoffset;
01167                 sp->ttis[1].tt_isdst = TRUE;
01168                 sp->ttis[1].tt_abbrind = stdlen + 1;
01169                 sp->typecnt = 2;
01170             }
01171         } else {
01172             dstlen = 0;
01173             sp->typecnt = 1;            /* only standard time */
01174             sp->timecnt = 0;
01175             sp->ttis[0].tt_gmtoff = -stdoffset;
01176             sp->ttis[0].tt_isdst = 0;
01177             sp->ttis[0].tt_abbrind = 0;
01178         }
01179         sp->charcnt = stdlen + 1;
01180         if (dstlen != 0)
01181             sp->charcnt += dstlen + 1;
01182         if ((size_t) sp->charcnt > sizeof sp->chars)
01183             return -1;
01184         cp = sp->chars;
01185         (void) strncpy(cp, stdname, stdlen);
01186         cp += stdlen;
01187         *cp++ = '\0';
01188         if (dstlen != 0) {
01189             (void) strncpy(cp, dstname, dstlen);
01190             *(cp + dstlen) = '\0';
01191         }
01192         return 0;
01193     }
01194 
01195     static int typesequiv(const struct state * const sp, const int a, const int b) {
01196         int     result;
01197 
01198         if (sp == NULL ||
01199             a < 0 || a >= sp->typecnt ||
01200             b < 0 || b >= sp->typecnt)
01201             result = FALSE;
01202         else {
01203             const struct ttinfo * ap = &sp->ttis[a];
01204             const struct ttinfo * bp = &sp->ttis[b];
01205             result = ap->tt_gmtoff == bp->tt_gmtoff &&
01206                 ap->tt_isdst == bp->tt_isdst &&
01207                 ap->tt_ttisstd == bp->tt_ttisstd &&
01208                 ap->tt_ttisgmt == bp->tt_ttisgmt &&
01209                 strcmp(&sp->chars[ap->tt_abbrind],
01210                        &sp->chars[bp->tt_abbrind]) == 0;
01211         }
01212         return result;
01213     }
01214 
01215     static int leaps_thru_end_of(const int y) {
01216         return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01217             -(leaps_thru_end_of(-(y + 1)) + 1);
01218     }
01219 
01220     static struct tm * timesub(const time_t * const timep, const long offset, const struct state * const sp, struct tm * const tmp) {
01221         const struct lsinfo * lp;
01222         time_t tdays;
01223         int     idays;  /* unsigned would be so 2003 */
01224         long rem;
01225         int      y;
01226         const int *     ip;
01227         long corr;
01228         int      hit;
01229         int      i;
01230 
01231         corr = 0;
01232         hit = 0;
01233         i = sp->leapcnt;
01234         while (--i >= 0) {
01235             lp = &sp->lsis[i];
01236             if (*timep >= lp->ls_trans) {
01237                 if (*timep == lp->ls_trans) {
01238                     hit = ((i == 0 && lp->ls_corr > 0) ||
01239                            lp->ls_corr > sp->lsis[i - 1].ls_corr);
01240                     if (hit)
01241                         while (i > 0 &&
01242                                sp->lsis[i].ls_trans ==
01243                                sp->lsis[i - 1].ls_trans + 1 &&
01244                                sp->lsis[i].ls_corr ==
01245                                sp->lsis[i - 1].ls_corr + 1) {
01246                             ++hit;
01247                             --i;
01248                         }
01249                 }
01250                 corr = lp->ls_corr;
01251                 break;
01252             }
01253         }
01254         y = EPOCH_YEAR;
01255         tdays = *timep / SECSPERDAY;
01256         rem = *timep - tdays * SECSPERDAY;
01257         while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
01258             int  newy;
01259             time_t tdelta;
01260             int idelta;
01261             int leapdays;
01262 
01263             tdelta = tdays / DAYSPERLYEAR;
01264             idelta = tdelta;
01265             if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01266                 return NULL;
01267             if (idelta == 0)
01268                 idelta = (tdays < 0) ? -1 : 1;
01269             newy = y;
01270             if (increment_overflow(&newy, idelta))
01271                 return NULL;
01272             leapdays = leaps_thru_end_of(newy - 1) -
01273                 leaps_thru_end_of(y - 1);
01274             tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
01275             tdays -= leapdays;
01276             y = newy;
01277         }
01278         {
01279             long seconds;
01280 
01281             seconds = tdays * SECSPERDAY + 0.5;
01282             tdays = seconds / SECSPERDAY;
01283             rem += seconds - tdays * SECSPERDAY;
01284         }
01285         /*
01286         ** Given the range, we can now fearlessly cast...
01287         */
01288         idays = tdays;
01289         rem += offset - corr;
01290         while (rem < 0) {
01291             rem += SECSPERDAY;
01292             --idays;
01293         }
01294         while (rem >= SECSPERDAY) {
01295             rem -= SECSPERDAY;
01296             ++idays;
01297         }
01298         while (idays < 0) {
01299             if (increment_overflow(&y, -1))
01300                 return NULL;
01301             idays += year_lengths[isleap(y)];
01302         }
01303         while (idays >= year_lengths[isleap(y)]) {
01304             idays -= year_lengths[isleap(y)];
01305             // if (increment_overflow(&y, 1)) // commented-out because of nasty g++ -Wall comment 
01306             //  return NULL;
01307         }
01308         tmp->tm_year = y;
01309         // if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) // commented-out because of nasty g++ -Wall comment
01310         //     return NULL;
01311         tmp->tm_yday = idays;
01312         /*
01313         ** The "extra" mods below avoid overflow problems.
01314         */
01315         tmp->tm_wday = EPOCH_WDAY +
01316             ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01317             (DAYSPERNYEAR % DAYSPERWEEK) +
01318             leaps_thru_end_of(y - 1) -
01319             leaps_thru_end_of(EPOCH_YEAR - 1) +
01320             idays;
01321         tmp->tm_wday %= DAYSPERWEEK;
01322         if (tmp->tm_wday < 0)
01323             tmp->tm_wday += DAYSPERWEEK;
01324         tmp->tm_hour = (int) (rem / SECSPERHOUR);
01325         rem %= SECSPERHOUR;
01326         tmp->tm_min = (int) (rem / SECSPERMIN);
01327         /*
01328         ** A positive leap second requires a special
01329         ** representation. This uses "... ??:59:60" et seq.
01330         */
01331         tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01332         ip = mon_lengths[isleap(y)];
01333         for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01334             idays -= ip[tmp->tm_mon];
01335         tmp->tm_mday = (int) (idays + 1);
01336         tmp->tm_isdst = 0;
01337 #ifdef TM_GMTOFF
01338         tmp->TM_GMTOFF = offset;
01339 #endif /* defined TM_GMTOFF */
01340         return tmp;
01341     }
01342 
01343     static void gmtload(struct state * const sp) {
01344         if (tzload(gmt, sp, TRUE) != 0)
01345             (void) tzparse(gmt, sp, TRUE);
01346     }
01347 
01348     static struct tm * gmtsub(const time_t * const timep, const long offset, struct tm * const  tmp) {
01349         struct tm * result;
01350 
01351         if (!gmt_is_set) {
01352             gmt_is_set = TRUE;
01353             gmtload(gmtptr);
01354         }
01355         result = timesub(timep, offset, gmtptr, tmp);
01356         return result;
01357     }
01358 
01359     static struct tm * gmtime_(const time_t * const     timep) {
01360         return gmtsub(timep, 0L, &tm);
01361     }
01362 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines