|
Rcpp Version 0.9.10
|
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 ©) { 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 }