Rcpp Version 0.10.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros
Date.cpp
Go to the documentation of this file.
1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 // jedit: :folding=explicit:
3 //
4 // Date.cpp: Rcpp R/C++ interface class library -- Date type
5 //
6 // Copyright (C) 2010 - 2012 Dirk Eddelbuettel and Romain Francois
7 //
8 // The mktime00() as well as the gmtime_() replacement function are
9 // Copyright (C) 2000 - 2010 The R Development Core Team.
10 //
11 // gmtime_() etc are from the public domain timezone code dated
12 // 1996-06-05 by Arthur David Olson.
13 //
14 // This file is part of Rcpp.
15 //
16 // Rcpp is free software: you can redistribute it and/or modify it
17 // under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 2 of the License, or
19 // (at your option) any later version.
20 //
21 // Rcpp is distributed in the hope that it will be useful, but
22 // WITHOUT ANY WARRANTY; without even the implied warranty of
23 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 // GNU General Public License for more details.
25 //
26 // You should have received a copy of the GNU General Public License
27 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
28 
29 #include <Rcpp/Datetime.h>
30 #include <Rcpp/Date.h>
31 #include <Rcpp/DatetimeVector.h>
32 #include <Rcpp/DateVector.h>
33 
34 #include <Rcpp/Function.h>
35 #include <Rmath.h> // for Rf_fround
36 #include <time.h> // for gmtime
37 #include <Rcpp/exceptions.h>
38 
39 namespace Rcpp {
40 
41  static struct tm * gmtime_(const time_t * const timep); // see below
42 
43  // {{{ Date
44  const unsigned int Date::QLtoJan1970Offset = 25569; // Offset between R / Unix epoch date and the QL base date
45  const unsigned int Date::baseYear = 1900; // because we hate macros
46 
48  m_d = 0;
49  update_tm();
50  }
51 
52  Date::Date(SEXP d) {
53  m_d = Rcpp::as<double>(d);
54  update_tm();
55  }
56 
57  Date::Date(const int &dt) {
58  m_d = dt;
59  update_tm();
60  }
61 
62  Date::Date(const double &dt) {
63  m_d = dt;
64  update_tm();
65  }
66 
67  Date::Date(const std::string &s, const std::string &fmt) {
68  Rcpp::Function strptime("strptime"); // we cheat and call strptime() from R
69  Rcpp::Function asDate("as.Date"); // and we need to convert to Date
70  m_d = Rcpp::as<int>(asDate(strptime(s, fmt, "UTC")));
71  update_tm();
72  }
73 
74  Date::Date(const unsigned int &mon, const unsigned int &day, const unsigned int &year) {
75 
76  m_tm.tm_sec = m_tm.tm_min = m_tm.tm_hour = m_tm.tm_isdst = 0;
77 
78  // allow for ISO-notation case (yyyy, mm, dd) which we prefer over (mm, dd, year)
79  if (mon >= baseYear && day <= 12 && year <= 31) {
80  m_tm.tm_year = mon - baseYear;
81  m_tm.tm_mon = day - 1; // range 0 to 11
82  m_tm.tm_mday = year;
83  } else {
84  m_tm.tm_mday = day;
85  m_tm.tm_mon = mon - 1; // range 0 to 11
86  m_tm.tm_year = year - baseYear;
87  }
88  double tmp = mktime00(m_tm); // use mktime() replacement borrowed from R
89  m_tm.tm_year += baseYear; // we'd rather keep it as a normal year
90  m_d = tmp/(24*60*60);
91  }
92 
93  Date::Date(const Date &copy) {
94  m_d = copy.m_d;
95  m_tm = copy.m_tm;
96  }
97 
98  Date & Date::operator=(const Date & newdate) {
99  if (this != &newdate) {
100  m_d = newdate.m_d;
101  m_tm = newdate.m_tm;
102  }
103  return *this;
104  }
105 
107  if (R_FINITE(m_d)) {
108  time_t t = 24*60*60 * m_d; // (fractional) days since epoch to seconds since epoch
109  m_tm = *gmtime_(&t);
110  } else {
111  m_tm.tm_sec = m_tm.tm_min = m_tm.tm_hour = m_tm.tm_isdst = NA_INTEGER;
112  m_tm.tm_min = m_tm.tm_hour = m_tm.tm_mday = m_tm.tm_mon = m_tm.tm_year = NA_INTEGER;
113  }
114  }
115 
116  // Taken from R's src/main/datetime.c and made a member function called with C++ reference
117  /* Substitute for mktime -- no checking, always in GMT */
118  double Date::mktime00(struct tm &tm) const {
119 
120  static const int days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
121 
122  #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
123  #define days_in_year(year) (isleap(year) ? 366 : 365)
124 
125  int day = 0;
126  int i, year, year0;
127  double excess = 0.0;
128 
129  day = tm.tm_mday - 1;
130  year0 = baseYear + tm.tm_year;
131  /* safety check for unbounded loops */
132  if (year0 > 3000) {
133  excess = (int)(year0/2000) - 1;
134  year0 -= excess * 2000;
135  } else if (year0 < 0) {
136  excess = -1 - (int)(-year0/2000);
137  year0 -= excess * 2000;
138  }
139 
140  for(i = 0; i < tm.tm_mon; i++) day += days_in_month[i];
141  if (tm.tm_mon > 1 && isleap(year0)) day++;
142  tm.tm_yday = day;
143 
144  if (year0 > 1970) {
145  for (year = 1970; year < year0; year++)
146  day += days_in_year(year);
147  } else if (year0 < 1970) {
148  for (year = 1969; year >= year0; year--)
149  day -= days_in_year(year);
150  }
151 
152  /* weekday: Epoch day was a Thursday */
153  if ((tm.tm_wday = (day + 4) % 7) < 0) tm.tm_wday += 7;
154 
155  return tm.tm_sec + (tm.tm_min * 60) + (tm.tm_hour * 3600)
156  + (day + excess * 730485) * 86400.0;
157  }
158  #undef isleap
159  #undef days_in_year
160 
161  Date operator+(const Date &date, int offset) {
162  Date newdate(date.m_d);
163  newdate.m_d += offset;
164  time_t t = 24*60*60 * newdate.m_d; // days since epoch to seconds since epo
165  //newdate.m_tm = *gmtime(&t); // this may need a Windows fix, re-check R's datetime.c
166  newdate.m_tm = *gmtime_(&t);
167  return newdate;
168  }
169 
170  int operator-(const Date& d1, const Date& d2) { return d2.m_d - d1.m_d; }
171  bool operator<(const Date &d1, const Date& d2) { return d1.m_d < d2.m_d; }
172  bool operator>(const Date &d1, const Date& d2) { return d1.m_d > d2.m_d; }
173  bool operator==(const Date &d1, const Date& d2) { return d1.m_d == d2.m_d; }
174  bool operator>=(const Date &d1, const Date& d2) { return d1.m_d >= d2.m_d; }
175  bool operator<=(const Date &d1, const Date& d2) { return d1.m_d <= d2.m_d; }
176  bool operator!=(const Date &d1, const Date& d2) { return d1.m_d != d2.m_d; }
177 
178  namespace internal{
179 
181  SEXP datetimeclass = PROTECT(Rf_allocVector(STRSXP,2));
182  SET_STRING_ELT(datetimeclass, 0, Rf_mkChar("POSIXct"));
183  SET_STRING_ELT(datetimeclass, 1, Rf_mkChar("POSIXt"));
184  UNPROTECT(1) ;
185  return datetimeclass ;
186  }
187 
188  SEXP new_posixt_object( double d){
189  SEXP x = PROTECT( Rf_ScalarReal( d ) ) ;
190  Rf_setAttrib(x, R_ClassSymbol, getPosixClasses() );
191  UNPROTECT(1);
192  return x ;
193  }
194 
195  SEXP new_date_object( double d){
196  SEXP x = PROTECT(Rf_ScalarReal( d ) ) ;
197  Rf_setAttrib(x, R_ClassSymbol, Rf_mkString("Date"));
198  UNPROTECT(1);
199  return x;
200  }
201 
202  }
203 
204  template <> SEXP wrap(const Date &date) {
205  return internal::new_date_object( date.getDate() ) ;
206  }
207  // }}}
208 
209  // {{{ Datetime
211  m_dt = 0;
212  update_tm();
213  }
214 
216  m_dt = Rcpp::as<double>(d);
217  update_tm();
218  }
219 
220  Datetime::Datetime(const double &dt) {
221  m_dt = dt;
222  update_tm();
223  }
224 
225  Datetime::Datetime(const std::string &s, const std::string &fmt) {
226  Rcpp::Function strptime("strptime"); // we cheat and call strptime() from R
227  Rcpp::Function asPOSIXct("as.POSIXct"); // and we need to convert to POSIXct
228  m_dt = Rcpp::as<double>(asPOSIXct(strptime(s, fmt)));
229  update_tm();
230  }
231 
233  m_dt = copy.m_dt;
234  m_us = copy.m_us;
235  m_tm = copy.m_tm;
236  }
237 
239  if (this != &newdt) {
240  m_dt = newdt.m_dt;
241  m_us = newdt.m_us;
242  m_tm = newdt.m_tm;
243  }
244  return *this;
245  }
246 
248  if (R_FINITE(m_dt)) {
249  time_t t = static_cast<time_t>(floor(m_dt));
250  m_tm = *gmtime(&t); // this may need a Windows fix, re-check R's datetime.c
251  // m_us is fractional (micro)secs as diff. between (fractional) m_dt and m_tm
252  m_us = static_cast<int>(::Rf_fround( (m_dt - t) * 1.0e6, 0.0));
253  } else {
254  m_dt = NA_REAL; // NaN and Inf need it set
255  m_tm.tm_sec = m_tm.tm_min = m_tm.tm_hour = m_tm.tm_isdst = NA_INTEGER;
256  m_tm.tm_min = m_tm.tm_hour = m_tm.tm_mday = m_tm.tm_mon = m_tm.tm_year = NA_INTEGER;
257  m_us = NA_INTEGER;
258  }
259  }
260 
261  Datetime operator+(const Datetime &datetime, double offset) {
262  Datetime newdt(datetime.m_dt);
263  newdt.m_dt += offset;
264  time_t t = static_cast<time_t>(floor(newdt.m_dt));
265  newdt.m_tm = *gmtime(&t); // this may need a Windows fix, re-check R's dat
266  newdt.m_us = static_cast<int>(::Rf_fround( (newdt.m_dt - t) * 1.0e6, 0.0));
267  return newdt;
268  }
269 
270  double operator-(const Datetime& d1, const Datetime& d2) { return d2.m_dt - d1.m_dt; }
271  bool operator<(const Datetime &d1, const Datetime& d2) { return d1.m_dt < d2.m_dt; }
272  bool operator>(const Datetime &d1, const Datetime& d2) { return d1.m_dt > d2.m_dt; }
273  bool operator==(const Datetime &d1, const Datetime& d2) { return d1.m_dt == d2.m_dt; }
274  bool operator>=(const Datetime &d1, const Datetime& d2) { return d1.m_dt >= d2.m_dt; }
275  bool operator<=(const Datetime &d1, const Datetime& d2) { return d1.m_dt <= d2.m_dt; }
276  bool operator!=(const Datetime &d1, const Datetime& d2) { return d1.m_dt != d2.m_dt; }
277 
278  template<> SEXP wrap_extra_steps<Rcpp::Datetime>( SEXP x ){
279  Rf_setAttrib(x, R_ClassSymbol, internal::getPosixClasses() );
280  return x ;
281  }
282 
283  template <> SEXP wrap(const Datetime &date) {
285  }
286  // }}}
287 
288  // {{{ DatetimeVector
290  int i;
291  if (!Rf_isNumeric(vec) || Rf_isMatrix(vec) || Rf_isLogical(vec))
292  throw std::range_error("DatetimeVector: invalid numeric vector in constructor");
293  int len = Rf_length(vec);
294  if (len == 0)
295  throw std::range_error("DatetimeVector: null vector in constructor");
296  v.resize(len);
297  for (i = 0; i < len; i++)
298  v[i] = Datetime( static_cast<double>(REAL(vec)[i]));
299  }
300 
301 
303 
304  const Datetime & DatetimeVector::operator()(int i) const {
305  if (i < 0 || i >= static_cast<int>(v.size())) {
306  std::ostringstream oss;
307  oss << "DatetimeVector: subscript out of range: " << i;
308  throw std::range_error(oss.str());
309  }
310  return v[i];
311  }
312 
314  if (i < 0 || i >= static_cast<int>(v.size())) {
315  std::ostringstream oss;
316  oss << "DatetimeVector: subscript out of range: " << i;
317  throw std::range_error(oss.str());
318  }
319  return v[i];
320  }
321 
322  const Datetime & DatetimeVector::operator[](int i) const {
323  if (i < 0 || i >= static_cast<int>(v.size())) {
324  std::ostringstream oss;
325  oss << "DatetimeVector: subscript out of range: " << i;
326  throw std::range_error(oss.str());
327  }
328  return v[i];
329  }
330 
332  if (i < 0 || i >= static_cast<int>(v.size())) {
333  std::ostringstream oss;
334  oss << "DatetimeVector: subscript out of range: " << i;
335  throw std::range_error(oss.str());
336  }
337  return v[i];
338  }
339 
340  int DatetimeVector::size() const {
341  return v.size();
342  }
343 
344  std::vector<Datetime> DatetimeVector::getDatetimes() const {
345  return v;
346  }
347  // }}}
348 
349  // {{{ DateVector
350  DateVector::DateVector(SEXP vec) : v() {
351  int i;
352  if (!Rf_isNumeric(vec) || Rf_isMatrix(vec) || Rf_isLogical(vec))
353  throw std::range_error("DateVector: invalid numeric vector in constructor");
354  int len = Rf_length(vec);
355  if (len == 0)
356  throw std::range_error("DateVector: null vector in constructor");
357  v.resize(len);
358  for (i = 0; i < len; i++)
359  v[i] = Date( static_cast<double>(REAL(vec)[i]));
360  }
361 
362 
364 
365  const Date & DateVector::operator()(int i) const {
366  if (i < 0 || i >= static_cast<int>(v.size())) {
367  std::ostringstream oss;
368  oss << "DateVector: subscript out of range: " << i;
369  throw std::range_error(oss.str());
370  }
371  return v[i];
372  }
373 
375  if (i < 0 || i >= static_cast<int>(v.size())) {
376  std::ostringstream oss;
377  oss << "DateVector: subscript out of range: " << i;
378  throw std::range_error(oss.str());
379  }
380  return v[i];
381  }
382 
383  const Date & DateVector::operator[](int i) const {
384  if (i < 0 || i >= static_cast<int>(v.size())) {
385  std::ostringstream oss;
386  oss << "DatetimeVector: subscript out of range: " << i;
387  throw std::range_error(oss.str());
388  }
389  return v[i];
390  }
391 
393  if (i < 0 || i >= static_cast<int>(v.size())) {
394  std::ostringstream oss;
395  oss << "DatetimeVector: subscript out of range: " << i;
396  throw std::range_error(oss.str());
397  }
398  return v[i];
399  }
400 
401  int DateVector::size() const {
402  return v.size();
403  }
404 
405  std::vector<Date> DateVector::getDates() const {
406  return v;
407  }
408  // }}}
409 
410 #include "sys/types.h" /* for time_t */
411 #include "string.h"
412 #include "limits.h" /* for CHAR_BIT et al. */
413 
414 #define _NO_OLDNAMES /* avoid tznames */
415 #include "time.h"
416 #undef _NO_OLDNAMES
417 
418 #include <errno.h>
419 #ifndef EOVERFLOW
420 # define EOVERFLOW 79
421 #endif
422 
423 #include "stdlib.h"
424 #include "stdint.h"
425 #include "stdio.h"
426 #include "fcntl.h"
427 #include "float.h" /* for FLT_MAX and DBL_MAX */
428 
429 #include <unistd.h> // solaris needs this for read() and close()
430 
431 
432 /* merged from private.h */
433 #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
434 #define TYPE_SIGNED(type) (((type) -1) < 0)
435 #define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
436 #define GRANDPARENTED "Local time zone must be set--see zic manual page"
437 #define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
438 #define AVGSECSPERYEAR 31556952L
439 #define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
440 #define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
441 #define is_digit(c) ((unsigned)(c) - '0' <= 9)
442 #define INITIALIZE(x) (x = 0)
443 
444  //#include "tzfile.h"
445  // BEGIN ------------------------------------------------------------------------------------------ tzfile.h
446 #ifndef TZFILE_H
447 
448 #define TZFILE_H
449 
450 /*
451 ** This file is in the public domain, so clarified as of
452 ** 1996-06-05 by Arthur David Olson.
453 */
454 
455 /*
456 ** This header is for use ONLY with the time conversion code.
457 ** There is no guarantee that it will remain unchanged,
458 ** or that it will remain at all.
459 ** Do NOT copy it to any system include directory.
460 ** Thank you!
461 */
462 
463 /*
464 ** Information about time zone files.
465 */
466 
467 #ifndef TZDIR
468 #define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */
469 #endif /* !defined TZDIR */
470 
471 #ifndef TZDEFAULT
472 #define TZDEFAULT "localtime"
473 #endif /* !defined TZDEFAULT */
474 
475 #ifndef TZDEFRULES
476 #define TZDEFRULES "America/New_York"
477 #endif /* !defined TZDEFRULES */
478 
479 /*
480 ** Each file begins with. . .
481 */
482 
483 #define TZ_MAGIC "TZif"
484 
485 struct tzhead {
486  char tzh_magic[4]; /* TZ_MAGIC */
487  char tzh_version[1]; /* '\0' or '2' as of 2005 */
488  char tzh_reserved[15]; /* reserved--must be zero */
489  char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
490  char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
491  char tzh_leapcnt[4]; /* coded number of leap seconds */
492  char tzh_timecnt[4]; /* coded number of transition times */
493  char tzh_typecnt[4]; /* coded number of local time types */
494  char tzh_charcnt[4]; /* coded number of abbr. chars */
495 };
496 
497 /*
498 ** . . .followed by. . .
499 **
500 ** tzh_timecnt (char [4])s coded transition times a la time(2)
501 ** tzh_timecnt (unsigned char)s types of local time starting at above
502 ** tzh_typecnt repetitions of
503 ** one (char [4]) coded UTC offset in seconds
504 ** one (unsigned char) used to set tm_isdst
505 ** one (unsigned char) that's an abbreviation list index
506 ** tzh_charcnt (char)s '\0'-terminated zone abbreviations
507 ** tzh_leapcnt repetitions of
508 ** one (char [4]) coded leap second transition times
509 ** one (char [4]) total correction after above
510 ** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
511 ** time is standard time, if FALSE,
512 ** transition time is wall clock time
513 ** if absent, transition times are
514 ** assumed to be wall clock time
515 ** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
516 ** time is UTC, if FALSE,
517 ** transition time is local time
518 ** if absent, transition times are
519 ** assumed to be local time
520 */
521 
522 /*
523 ** If tzh_version is '2' or greater, the above is followed by a second instance
524 ** of tzhead and a second instance of the data in which each coded transition
525 ** time uses 8 rather than 4 chars,
526 ** then a POSIX-TZ-environment-variable-style string for use in handling
527 ** instants after the last transition time stored in the file
528 ** (with nothing between the newlines if there is no POSIX representation for
529 ** such instants).
530 */
531 
532 /*
533 ** In the current implementation, "tzset()" refuses to deal with files that
534 ** exceed any of the limits below.
535 */
536 
537 #ifndef TZ_MAX_TIMES
538 #define TZ_MAX_TIMES 1200
539 #endif /* !defined TZ_MAX_TIMES */
540 
541 #ifndef TZ_MAX_TYPES
542 #ifndef NOSOLAR
543 #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
544 #endif /* !defined NOSOLAR */
545 #ifdef NOSOLAR
546 /*
547 ** Must be at least 14 for Europe/Riga as of Jan 12 1995,
548 ** as noted by Earl Chew.
549 */
550 #define TZ_MAX_TYPES 20 /* Maximum number of local time types */
551 #endif /* !defined NOSOLAR */
552 #endif /* !defined TZ_MAX_TYPES */
553 
554 #ifndef TZ_MAX_CHARS
555 #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
556  /* (limited by what unsigned chars can hold) */
557 #endif /* !defined TZ_MAX_CHARS */
558 
559 #ifndef TZ_MAX_LEAPS
560 #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
561 #endif /* !defined TZ_MAX_LEAPS */
562 
563 #define SECSPERMIN 60
564 #define MINSPERHOUR 60
565 #define HOURSPERDAY 24
566 #define DAYSPERWEEK 7
567 #define DAYSPERNYEAR 365
568 #define DAYSPERLYEAR 366
569 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
570 #define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
571 #define MONSPERYEAR 12
572 
573 #define TM_SUNDAY 0
574 #define TM_MONDAY 1
575 #define TM_TUESDAY 2
576 #define TM_WEDNESDAY 3
577 #define TM_THURSDAY 4
578 #define TM_FRIDAY 5
579 #define TM_SATURDAY 6
580 
581 #define TM_JANUARY 0
582 #define TM_FEBRUARY 1
583 #define TM_MARCH 2
584 #define TM_APRIL 3
585 #define TM_MAY 4
586 #define TM_JUNE 5
587 #define TM_JULY 6
588 #define TM_AUGUST 7
589 #define TM_SEPTEMBER 8
590 #define TM_OCTOBER 9
591 #define TM_NOVEMBER 10
592 #define TM_DECEMBER 11
593 
594 #define TM_YEAR_BASE baseYear // was: 1900, baseYear defined above
595 
596 #define EPOCH_YEAR 1970
597 #define EPOCH_WDAY TM_THURSDAY
598 
599 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
600 
601 /*
602 ** Since everything in isleap is modulo 400 (or a factor of 400), we know that
603 ** isleap(y) == isleap(y % 400)
604 ** and so
605 ** isleap(a + b) == isleap((a + b) % 400)
606 ** or
607 ** isleap(a + b) == isleap(a % 400 + b % 400)
608 ** This is true even if % means modulo rather than Fortran remainder
609 ** (which is allowed by C89 but not C99).
610 ** We use this to avoid addition overflow problems.
611 */
612 
613 #define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
614 
615 #endif /* !defined TZFILE_H */
616 
617  // -------------------------------------------------------------------------------------- END tzfile.h
618 
619 #ifdef O_BINARY
620 #define OPEN_MODE (O_RDONLY | O_BINARY)
621 #endif /* defined O_BINARY */
622 #ifndef O_BINARY
623 #define OPEN_MODE O_RDONLY
624 #endif /* !defined O_BINARY */
625 
626  static const char gmt[] = "GMT";
627 
628  /*
629  ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
630  ** We default to US rules as of 1999-08-17.
631  ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
632  ** implementation dependent; for historical reasons, US rules are a
633  ** common default.
634  */
635 #ifndef TZDEFRULESTRING
636 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
637 #endif /* !defined TZDEFDST */
638 
639 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
640 
641 #ifdef TZNAME_MAX
642 #define MY_TZNAME_MAX TZNAME_MAX
643 #endif /* defined TZNAME_MAX */
644 #ifndef TZNAME_MAX
645 #define MY_TZNAME_MAX 255
646 #endif /* !defined TZNAME_MAX */
647 
648  struct ttinfo { /* time type information */
649  long tt_gmtoff; /* UTC offset in seconds */
650  int tt_isdst; /* used to set tm_isdst */
651  int tt_abbrind; /* abbreviation list index */
652  int tt_ttisstd; /* TRUE if transition is std time */
653  int tt_ttisgmt; /* TRUE if transition is UTC */
654  };
655 
656  struct lsinfo { /* leap second information */
657  time_t ls_trans; /* transition time */
658  long ls_corr; /* correction to apply */
659  };
660 
661  struct state {
662  int leapcnt;
663  int timecnt;
664  int typecnt;
665  int charcnt;
666  int goback;
667  int goahead;
668  time_t ats[TZ_MAX_TIMES];
669  unsigned char types[TZ_MAX_TIMES];
671  char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
672  (2 * (MY_TZNAME_MAX + 1)))];
674  };
675 
676  struct rule {
677  int r_type; /* type of rule--see below */
678  int r_day; /* day number of rule */
679  int r_week; /* week number of rule */
680  int r_mon; /* month number of rule */
681  long r_time; /* transition time of rule */
682  };
683 
684 #define JULIAN_DAY 0 /* Jn - Julian day */
685 #define DAY_OF_YEAR 1 /* n - day of year */
686 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
687 
688  static const int mon_lengths[2][MONSPERYEAR] = {
689  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
690  { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
691  };
692 
693  static const int year_lengths[2] = {
695  };
696 
697  static int gmt_is_set;
698 
699  //static struct state lclmem;
700  static struct state gmtmem;
701  //#define lclptr (&lclmem)
702 #define gmtptr (&gmtmem)
703 
704  static struct tm tm;
705 
706  //extern const char *getTZinfo(void);
707 
708  static int tzparse(const char * name, struct state * sp, int lastditch);
709  static int typesequiv(const struct state * sp, int a, int b);
710  static const char * getsecs(const char * strp, long * secsp);
711  static const char * getnum(const char * strp, int * const nump, const int min, const int max);
712  static const char * getrule(const char * strp, struct rule * const rulep);
713  static time_t transtime(const time_t janfirst, const int year, const struct rule * const rulep, const long offset);
714  static struct tm * timesub(const time_t * const timep, const long offset, const struct state * const sp, struct tm * const tmp);
715  static int leaps_thru_end_of(const int y);
716 
717  static int increment_overflow(int * number, int delta) {
718  int number0;
719 
720  number0 = *number;
721  *number += delta;
722  return (*number < number0) != (delta < 0);
723  }
724 
725  static long detzcode(const char * const codep) {
726  long result;
727  int i;
728 
729  result = (codep[0] & 0x80) ? ~0L : 0;
730  for (i = 0; i < 4; ++i)
731  result = (result << 8) | (codep[i] & 0xff);
732  return result;
733  }
734 
735  static time_t detzcode64(const char * const codep) {
736  time_t result;
737  int i;
738 
739  result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
740  for (i = 0; i < 8; ++i)
741  result = result * 256 + (codep[i] & 0xff);
742  return result;
743  }
744 
745  static int differ_by_repeat(const time_t t1, const time_t t0) {
746  if (TYPE_INTEGRAL(time_t) &&
747  TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
748  return 0;
749  /* R change */
750  return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT;
751  }
752 
753  static const char * getzname(const char * strp) {
754  char c;
755 
756  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
757  c != '+')
758  ++strp;
759  return strp;
760  }
761 
762  static const char * getqzname(const char *strp, const int delim) {
763  int c;
764 
765  while ((c = *strp) != '\0' && c != delim)
766  ++strp;
767  return strp;
768  }
769 
770  static const char * getoffset(const char * strp, long * const offsetp) {
771  int neg = 0;
772 
773  if (*strp == '-') {
774  neg = 1;
775  ++strp;
776  } else if (*strp == '+')
777  ++strp;
778  strp = getsecs(strp, offsetp);
779  if (strp == NULL)
780  return NULL; /* illegal time */
781  if (neg)
782  *offsetp = -*offsetp;
783  return strp;
784  }
785 
786  static const char * getsecs( const char * strp, long * const secsp) {
787  int num;
788 
789  /*
790  ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
791  ** "M10.4.6/26", which does not conform to Posix,
792  ** but which specifies the equivalent of
793  ** ``02:00 on the first Sunday on or after 23 Oct''.
794  */
795  strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
796  if (strp == NULL)
797  return NULL;
798  *secsp = num * (long) SECSPERHOUR;
799  if (*strp == ':') {
800  ++strp;
801  strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
802  if (strp == NULL)
803  return NULL;
804  *secsp += num * SECSPERMIN;
805  if (*strp == ':') {
806  ++strp;
807  /* `SECSPERMIN' allows for leap seconds. */
808  strp = getnum(strp, &num, 0, SECSPERMIN);
809  if (strp == NULL)
810  return NULL;
811  *secsp += num;
812  }
813  }
814  return strp;
815  }
816 
817  static const char * getnum(const char * strp, int * const nump, const int min, const int max) {
818  char c;
819  int num;
820 
821  if (strp == NULL || !is_digit(c = *strp))
822  return NULL;
823  num = 0;
824  do {
825  num = num * 10 + (c - '0');
826  if (num > max)
827  return NULL; /* illegal value */
828  c = *++strp;
829  } while (is_digit(c));
830  if (num < min)
831  return NULL; /* illegal value */
832  *nump = num;
833  return strp;
834  }
835 
836  static const char * getrule(const char * strp, struct rule * const rulep) {
837  if (*strp == 'J') {
838  /*
839  ** Julian day.
840  */
841  rulep->r_type = JULIAN_DAY;
842  ++strp;
843  strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
844  } else if (*strp == 'M') {
845  /*
846  ** Month, week, day.
847  */
848  rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
849  ++strp;
850  strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
851  if (strp == NULL)
852  return NULL;
853  if (*strp++ != '.')
854  return NULL;
855  strp = getnum(strp, &rulep->r_week, 1, 5);
856  if (strp == NULL)
857  return NULL;
858  if (*strp++ != '.')
859  return NULL;
860  strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
861  } else if (is_digit(*strp)) {
862  /*
863  ** Day of year.
864  */
865  rulep->r_type = DAY_OF_YEAR;
866  strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
867  } else return NULL; /* invalid format */
868  if (strp == NULL)
869  return NULL;
870  if (*strp == '/') {
871  /*
872  ** Time specified.
873  */
874  ++strp;
875  strp = getsecs(strp, &rulep->r_time);
876  } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
877  return strp;
878  }
879 
880  static int tzload(const char * name, struct state * const sp, const int doextend) {
881  const char * p;
882  int i;
883  int fid;
884  int stored;
885  int nread;
886  union {
887  struct tzhead tzhead;
888  char buf[2 * sizeof(struct tzhead) +
889  2 * sizeof *sp + 4 * TZ_MAX_TIMES];
890  } u;
891 
892  sp->goback = sp->goahead = FALSE;
893  /* if (name == NULL && (name = TZDEFAULT) == NULL) return -1; */
894  if (name == NULL) {
895  // edd 06 Jul 2010 let's do without getTZinfo()
896  //name = getTZinfo();
897  //if( strcmp(name, "unknown") == 0 ) name = TZDEFAULT;
898  name = TZDEFAULT;
899  }
900 
901  {
902  int doaccess;
903  /*
904  ** Section 4.9.1 of the C standard says that
905  ** "FILENAME_MAX expands to an integral constant expression
906  ** that is the size needed for an array of char large enough
907  ** to hold the longest file name string that the implementation
908  ** guarantees can be opened."
909  */
910  char fullname[FILENAME_MAX + 1];
911  // edd 08 Jul 2010 not currently needed const char *sname = name;
912 
913  if (name[0] == ':')
914  ++name;
915  doaccess = name[0] == '/';
916  if (!doaccess) {
917  char buf[1000];
918  p = getenv("TZDIR");
919  if (p == NULL) {
920  snprintf(buf, 1000, "%s/share/zoneinfo",
921  getenv("R_HOME"));
922  buf[999] = '\0';
923  p = buf;
924  }
925  /* if ((p = TZDIR) == NULL) return -1; */
926  if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
927  return -1;
928  (void) strcpy(fullname, p);
929  (void) strcat(fullname, "/");
930  (void) strcat(fullname, name);
931  /*
932  ** Set doaccess if '.' (as in "../") shows up in name.
933  */
934  if (strchr(name, '.') != NULL) doaccess = TRUE;
935  name = fullname;
936  }
937  // edd 16 Jul 2010 comment out whole block
938  //if (doaccess && access(name, R_OK) != 0) {
939  // edd 08 Jul 2010 we use this without TZ for dates only
940  // so no need to warn
941  //Rf_warning("unknown timezone '%s'", sname);
942  //return -1;
943  //}
944  if ((fid = open(name, OPEN_MODE)) == -1) {
945  // edd 08 Jul 2010 we use this without TZ for dates only
946  // so no need to warn
947  //Rf_warning("unknown timezone '%s'", sname);
948  return -1;
949  }
950 
951  }
952  nread = read(fid, u.buf, sizeof u.buf);
953  if (close(fid) < 0 || nread <= 0)
954  return -1;
955  for (stored = 4; stored <= 8; stored *= 2) {
956  int ttisstdcnt;
957  int ttisgmtcnt;
958 
959  ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
960  ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
961  sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
962  sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
963  sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
964  sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
965  p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
966  if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
967  sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
968  sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
969  sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
970  (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
971  (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
972  return -1;
973  if (nread - (p - u.buf) <
974  sp->timecnt * stored + /* ats */
975  sp->timecnt + /* types */
976  sp->typecnt * 6 + /* ttinfos */
977  sp->charcnt + /* chars */
978  sp->leapcnt * (stored + 4) + /* lsinfos */
979  ttisstdcnt + /* ttisstds */
980  ttisgmtcnt) /* ttisgmts */
981  return -1;
982  for (i = 0; i < sp->timecnt; ++i) {
983  sp->ats[i] = (stored == 4) ? detzcode(p) : detzcode64(p);
984  p += stored;
985  }
986  for (i = 0; i < sp->timecnt; ++i) {
987  sp->types[i] = (unsigned char) *p++;
988  if (sp->types[i] >= sp->typecnt)
989  return -1;
990  }
991  for (i = 0; i < sp->typecnt; ++i) {
992  struct ttinfo * ttisp;
993 
994  ttisp = &sp->ttis[i];
995  ttisp->tt_gmtoff = detzcode(p);
996  p += 4;
997  ttisp->tt_isdst = (unsigned char) *p++;
998  if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
999  return -1;
1000  ttisp->tt_abbrind = (unsigned char) *p++;
1001  if (ttisp->tt_abbrind < 0 ||
1002  ttisp->tt_abbrind > sp->charcnt)
1003  return -1;
1004  }
1005  for (i = 0; i < sp->charcnt; ++i)
1006  sp->chars[i] = *p++;
1007  sp->chars[i] = '\0'; /* ensure '\0' at end */
1008  for (i = 0; i < sp->leapcnt; ++i) {
1009  struct lsinfo * lsisp;
1010 
1011  lsisp = &sp->lsis[i];
1012  lsisp->ls_trans = (stored == 4) ? detzcode(p) : detzcode64(p);
1013  p += stored;
1014  lsisp->ls_corr = detzcode(p);
1015  p += 4;
1016  }
1017  for (i = 0; i < sp->typecnt; ++i) {
1018  struct ttinfo * ttisp;
1019 
1020  ttisp = &sp->ttis[i];
1021  if (ttisstdcnt == 0)
1022  ttisp->tt_ttisstd = FALSE;
1023  else {
1024  ttisp->tt_ttisstd = *p++;
1025  if (ttisp->tt_ttisstd != TRUE && ttisp->tt_ttisstd != FALSE)
1026  return -1;
1027  }
1028  }
1029  for (i = 0; i < sp->typecnt; ++i) {
1030  struct ttinfo * ttisp;
1031 
1032  ttisp = &sp->ttis[i];
1033  if (ttisgmtcnt == 0)
1034  ttisp->tt_ttisgmt = FALSE;
1035  else {
1036  ttisp->tt_ttisgmt = *p++;
1037  if (ttisp->tt_ttisgmt != TRUE && ttisp->tt_ttisgmt != FALSE)
1038  return -1;
1039  }
1040  }
1041  /*
1042  ** Out-of-sort ats should mean we're running on a
1043  ** signed time_t system but using a data file with
1044  ** unsigned values (or vice versa).
1045  */
1046  for (i = 0; i < sp->timecnt - 2; ++i)
1047  if (sp->ats[i] > sp->ats[i + 1]) {
1048  ++i;
1049  if (TYPE_SIGNED(time_t)) {
1050  /*
1051  ** Ignore the end (easy).
1052  */
1053  sp->timecnt = i;
1054  } else {
1055  /*
1056  ** Ignore the beginning (harder).
1057  */
1058  int j;
1059 
1060  for (j = 0; j + i < sp->timecnt; ++j) {
1061  sp->ats[j] = sp->ats[j + i];
1062  sp->types[j] = sp->types[j + i];
1063  }
1064  sp->timecnt = j;
1065  }
1066  break;
1067  }
1068  /*
1069  ** If this is an old file, we're done.
1070  */
1071  if (u.tzhead.tzh_version[0] == '\0')
1072  break;
1073  nread -= p - u.buf;
1074  for (i = 0; i < nread; ++i)
1075  u.buf[i] = p[i];
1076  /*
1077  ** If this is a narrow integer time_t system, we're done.
1078  */
1079  if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
1080  break;
1081  }
1082  if (doextend && nread > 2 &&
1083  u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
1084  sp->typecnt + 2 <= TZ_MAX_TYPES) {
1085  struct state ts;
1086  int result;
1087 
1088  u.buf[nread - 1] = '\0';
1089  result = tzparse(&u.buf[1], &ts, FALSE);
1090  if (result == 0 && ts.typecnt == 2 &&
1091  sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
1092  for (i = 0; i < 2; ++i)
1093  ts.ttis[i].tt_abbrind += sp->charcnt;
1094  for (i = 0; i < ts.charcnt; ++i)
1095  sp->chars[sp->charcnt++] = ts.chars[i];
1096  i = 0;
1097  while (i < ts.timecnt && ts.ats[i] <= sp->ats[sp->timecnt - 1])
1098  ++i;
1099  while (i < ts.timecnt &&
1100  sp->timecnt < TZ_MAX_TIMES) {
1101  sp->ats[sp->timecnt] = ts.ats[i];
1102  sp->types[sp->timecnt] = sp->typecnt + ts.types[i];
1103  ++sp->timecnt;
1104  ++i;
1105  }
1106  sp->ttis[sp->typecnt++] = ts.ttis[0];
1107  sp->ttis[sp->typecnt++] = ts.ttis[1];
1108  }
1109  }
1110  i = 2 * YEARSPERREPEAT;
1111  sp->goback = sp->goahead = sp->timecnt > i;
1112  sp->goback = sp->goback &&
1113  typesequiv(sp, sp->types[i], sp->types[0]) &&
1114  differ_by_repeat(sp->ats[i], sp->ats[0]);
1115  sp->goahead = sp->goahead &&
1116  typesequiv(sp, sp->types[sp->timecnt - 1],
1117  sp->types[sp->timecnt - 1 - i]) &&
1118  differ_by_repeat(sp->ats[sp->timecnt - 1],
1119  sp->ats[sp->timecnt - 1 - i]);
1120  return 0;
1121  }
1122 
1123  static time_t transtime(const time_t janfirst, const int year, const struct rule * const rulep, const long offset) {
1124  int leapyear;
1125  time_t value;
1126  int i;
1127  int d, m1, yy0, yy1, yy2, dow;
1128 
1129  INITIALIZE(value);
1130  leapyear = isleap(year);
1131  switch (rulep->r_type) {
1132 
1133  case JULIAN_DAY:
1134  /*
1135  ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1136  ** years.
1137  ** In non-leap years, or if the day number is 59 or less, just
1138  ** add SECSPERDAY times the day number-1 to the time of
1139  ** January 1, midnight, to get the day.
1140  */
1141  value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
1142  if (leapyear && rulep->r_day >= 60)
1143  value += SECSPERDAY;
1144  break;
1145 
1146  case DAY_OF_YEAR:
1147  /*
1148  ** n - day of year.
1149  ** Just add SECSPERDAY times the day number to the time of
1150  ** January 1, midnight, to get the day.
1151  */
1152  value = janfirst + rulep->r_day * SECSPERDAY;
1153  break;
1154 
1155  case MONTH_NTH_DAY_OF_WEEK:
1156  /*
1157  ** Mm.n.d - nth "dth day" of month m.
1158  */
1159  value = janfirst;
1160  for (i = 0; i < rulep->r_mon - 1; ++i)
1161  value += mon_lengths[leapyear][i] * SECSPERDAY;
1162 
1163  /*
1164  ** Use Zeller's Congruence to get day-of-week of first day of
1165  ** month.
1166  */
1167  m1 = (rulep->r_mon + 9) % 12 + 1;
1168  yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1169  yy1 = yy0 / 100;
1170  yy2 = yy0 % 100;
1171  dow = ((26 * m1 - 2) / 10 +
1172  1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1173  if (dow < 0)
1174  dow += DAYSPERWEEK;
1175 
1176  /*
1177  ** "dow" is the day-of-week of the first day of the month. Get
1178  ** the day-of-month (zero-origin) of the first "dow" day of the
1179  ** month.
1180  */
1181  d = rulep->r_day - dow;
1182  if (d < 0)
1183  d += DAYSPERWEEK;
1184  for (i = 1; i < rulep->r_week; ++i) {
1185  if (d + DAYSPERWEEK >=
1186  mon_lengths[leapyear][rulep->r_mon - 1])
1187  break;
1188  d += DAYSPERWEEK;
1189  }
1190 
1191  /*
1192  ** "d" is the day-of-month (zero-origin) of the day we want.
1193  */
1194  value += d * SECSPERDAY;
1195  break;
1196  }
1197 
1198  /*
1199  ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
1200  ** question. To get the Epoch-relative time of the specified local
1201  ** time on that day, add the transition time and the current offset
1202  ** from UTC.
1203  */
1204  return value + rulep->r_time + offset;
1205  }
1206 
1207  static int tzparse(const char * name, struct state * const sp, const int lastditch) {
1208  const char * stdname;
1209  const char * dstname;
1210  size_t stdlen;
1211  size_t dstlen;
1212  long stdoffset;
1213  long dstoffset;
1214  time_t * atp;
1215  unsigned char * typep;
1216  char * cp;
1217  int load_result;
1218 
1219  INITIALIZE(dstname);
1220  stdname = name;
1221  if (lastditch) {
1222  stdlen = strlen(name); /* length of standard zone name */
1223  name += stdlen;
1224  if (stdlen >= sizeof sp->chars)
1225  stdlen = (sizeof sp->chars) - 1;
1226  stdoffset = 0;
1227  } else {
1228  if (*name == '<') {
1229  name++;
1230  stdname = name;
1231  name = getqzname(name, '>');
1232  if (*name != '>')
1233  return (-1);
1234  stdlen = name - stdname;
1235  name++;
1236  } else {
1237  name = getzname(name);
1238  stdlen = name - stdname;
1239  }
1240  if (*name == '\0')
1241  return -1;
1242  name = getoffset(name, &stdoffset);
1243  if (name == NULL)
1244  return -1;
1245  }
1246  load_result = tzload(TZDEFRULES, sp, FALSE);
1247  if (load_result != 0)
1248  sp->leapcnt = 0; /* so, we're off a little */
1249  if (*name != '\0') {
1250  if (*name == '<') {
1251  dstname = ++name;
1252  name = getqzname(name, '>');
1253  if (*name != '>')
1254  return -1;
1255  dstlen = name - dstname;
1256  name++;
1257  } else {
1258  dstname = name;
1259  name = getzname(name);
1260  dstlen = name - dstname; /* length of DST zone name */
1261  }
1262  if (*name != '\0' && *name != ',' && *name != ';') {
1263  name = getoffset(name, &dstoffset);
1264  if (name == NULL)
1265  return -1;
1266  } else dstoffset = stdoffset - SECSPERHOUR;
1267  if (*name == '\0' && load_result != 0)
1268  name = TZDEFRULESTRING;
1269  if (*name == ',' || *name == ';') {
1270  struct rule start;
1271  struct rule end;
1272  int year;
1273  time_t janfirst;
1274  time_t starttime;
1275  time_t endtime;
1276 
1277  ++name;
1278  if ((name = getrule(name, &start)) == NULL)
1279  return -1;
1280  if (*name++ != ',')
1281  return -1;
1282  if ((name = getrule(name, &end)) == NULL)
1283  return -1;
1284  if (*name != '\0')
1285  return -1;
1286  sp->typecnt = 2; /* standard time and DST */
1287  /*
1288  ** Two transitions per year, from EPOCH_YEAR forward.
1289  */
1290  sp->ttis[0].tt_gmtoff = -dstoffset;
1291  sp->ttis[0].tt_isdst = 1;
1292  sp->ttis[0].tt_abbrind = stdlen + 1;
1293  sp->ttis[1].tt_gmtoff = -stdoffset;
1294  sp->ttis[1].tt_isdst = 0;
1295  sp->ttis[1].tt_abbrind = 0;
1296  atp = sp->ats;
1297  typep = sp->types;
1298  janfirst = 0;
1299  sp->timecnt = 0;
1300  for (year = EPOCH_YEAR;
1301  sp->timecnt + 2 <= TZ_MAX_TIMES;
1302  ++year) {
1303  time_t newfirst;
1304 
1305  starttime = transtime(janfirst, year, &start,
1306  stdoffset);
1307  endtime = transtime(janfirst, year, &end,
1308  dstoffset);
1309  if (starttime > endtime) {
1310  *atp++ = endtime;
1311  *typep++ = 1; /* DST ends */
1312  *atp++ = starttime;
1313  *typep++ = 0; /* DST begins */
1314  } else {
1315  *atp++ = starttime;
1316  *typep++ = 0; /* DST begins */
1317  *atp++ = endtime;
1318  *typep++ = 1; /* DST ends */
1319  }
1320  sp->timecnt += 2;
1321  newfirst = janfirst;
1322  newfirst += year_lengths[isleap(year)] *
1323  SECSPERDAY;
1324  if (newfirst <= janfirst)
1325  break;
1326  janfirst = newfirst;
1327  }
1328  } else {
1329  long theirstdoffset;
1330  long theirdstoffset;
1331  long theiroffset;
1332  int isdst;
1333  int i;
1334  int j;
1335 
1336  if (*name != '\0')
1337  return -1;
1338  /*
1339  ** Initial values of theirstdoffset and theirdstoffset.
1340  */
1341  theirstdoffset = 0;
1342  for (i = 0; i < sp->timecnt; ++i) {
1343  j = sp->types[i];
1344  if (!sp->ttis[j].tt_isdst) {
1345  theirstdoffset =
1346  -sp->ttis[j].tt_gmtoff;
1347  break;
1348  }
1349  }
1350  theirdstoffset = 0;
1351  for (i = 0; i < sp->timecnt; ++i) {
1352  j = sp->types[i];
1353  if (sp->ttis[j].tt_isdst) {
1354  theirdstoffset =
1355  -sp->ttis[j].tt_gmtoff;
1356  break;
1357  }
1358  }
1359  /*
1360  ** Initially we're assumed to be in standard time.
1361  */
1362  isdst = FALSE;
1363  theiroffset = theirstdoffset;
1364  /*
1365  ** Now juggle transition times and types
1366  ** tracking offsets as you do.
1367  */
1368  for (i = 0; i < sp->timecnt; ++i) {
1369  j = sp->types[i];
1370  sp->types[i] = sp->ttis[j].tt_isdst;
1371  if (sp->ttis[j].tt_ttisgmt) {
1372  /* No adjustment to transition time */
1373  } else {
1374  /*
1375  ** If summer time is in effect, and the
1376  ** transition time was not specified as
1377  ** standard time, add the summer time
1378  ** offset to the transition time;
1379  ** otherwise, add the standard time
1380  ** offset to the transition time.
1381  */
1382  /*
1383  ** Transitions from DST to DDST
1384  ** will effectively disappear since
1385  ** POSIX provides for only one DST
1386  ** offset.
1387  */
1388  if (isdst && !sp->ttis[j].tt_ttisstd) {
1389  sp->ats[i] += dstoffset -
1390  theirdstoffset;
1391  } else {
1392  sp->ats[i] += stdoffset -
1393  theirstdoffset;
1394  }
1395  }
1396  theiroffset = -sp->ttis[j].tt_gmtoff;
1397  if (sp->ttis[j].tt_isdst)
1398  theirdstoffset = theiroffset;
1399  else theirstdoffset = theiroffset;
1400  }
1401  /*
1402  ** Finally, fill in ttis.
1403  ** ttisstd and ttisgmt need not be handled.
1404  */
1405  sp->ttis[0].tt_gmtoff = -stdoffset;
1406  sp->ttis[0].tt_isdst = FALSE;
1407  sp->ttis[0].tt_abbrind = 0;
1408  sp->ttis[1].tt_gmtoff = -dstoffset;
1409  sp->ttis[1].tt_isdst = TRUE;
1410  sp->ttis[1].tt_abbrind = stdlen + 1;
1411  sp->typecnt = 2;
1412  }
1413  } else {
1414  dstlen = 0;
1415  sp->typecnt = 1; /* only standard time */
1416  sp->timecnt = 0;
1417  sp->ttis[0].tt_gmtoff = -stdoffset;
1418  sp->ttis[0].tt_isdst = 0;
1419  sp->ttis[0].tt_abbrind = 0;
1420  }
1421  sp->charcnt = stdlen + 1;
1422  if (dstlen != 0)
1423  sp->charcnt += dstlen + 1;
1424  if ((size_t) sp->charcnt > sizeof sp->chars)
1425  return -1;
1426  cp = sp->chars;
1427  (void) strncpy(cp, stdname, stdlen);
1428  cp += stdlen;
1429  *cp++ = '\0';
1430  if (dstlen != 0) {
1431  (void) strncpy(cp, dstname, dstlen);
1432  *(cp + dstlen) = '\0';
1433  }
1434  return 0;
1435  }
1436 
1437  static int typesequiv(const struct state * const sp, const int a, const int b) {
1438  int result;
1439 
1440  if (sp == NULL ||
1441  a < 0 || a >= sp->typecnt ||
1442  b < 0 || b >= sp->typecnt)
1443  result = FALSE;
1444  else {
1445  const struct ttinfo * ap = &sp->ttis[a];
1446  const struct ttinfo * bp = &sp->ttis[b];
1447  result = ap->tt_gmtoff == bp->tt_gmtoff &&
1448  ap->tt_isdst == bp->tt_isdst &&
1449  ap->tt_ttisstd == bp->tt_ttisstd &&
1450  ap->tt_ttisgmt == bp->tt_ttisgmt &&
1451  strcmp(&sp->chars[ap->tt_abbrind],
1452  &sp->chars[bp->tt_abbrind]) == 0;
1453  }
1454  return result;
1455  }
1456 
1457  static int leaps_thru_end_of(const int y) {
1458  return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1459  -(leaps_thru_end_of(-(y + 1)) + 1);
1460  }
1461 
1462  static struct tm * timesub(const time_t * const timep, const long offset, const struct state * const sp, struct tm * const tmp) {
1463  const struct lsinfo * lp;
1464  time_t tdays;
1465  int idays; /* unsigned would be so 2003 */
1466  long rem;
1467  int y;
1468  const int * ip;
1469  long corr;
1470  int hit;
1471  int i;
1472 
1473  corr = 0;
1474  hit = 0;
1475  i = sp->leapcnt;
1476  while (--i >= 0) {
1477  lp = &sp->lsis[i];
1478  if (*timep >= lp->ls_trans) {
1479  if (*timep == lp->ls_trans) {
1480  hit = ((i == 0 && lp->ls_corr > 0) ||
1481  lp->ls_corr > sp->lsis[i - 1].ls_corr);
1482  if (hit)
1483  while (i > 0 &&
1484  sp->lsis[i].ls_trans ==
1485  sp->lsis[i - 1].ls_trans + 1 &&
1486  sp->lsis[i].ls_corr ==
1487  sp->lsis[i - 1].ls_corr + 1) {
1488  ++hit;
1489  --i;
1490  }
1491  }
1492  corr = lp->ls_corr;
1493  break;
1494  }
1495  }
1496  y = EPOCH_YEAR;
1497  tdays = *timep / SECSPERDAY;
1498  rem = *timep - tdays * SECSPERDAY;
1499  while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1500  int newy;
1501  time_t tdelta;
1502  int idelta;
1503  int leapdays;
1504 
1505  tdelta = tdays / DAYSPERLYEAR;
1506  idelta = tdelta;
1507  if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1508  return NULL;
1509  if (idelta == 0)
1510  idelta = (tdays < 0) ? -1 : 1;
1511  newy = y;
1512  if (increment_overflow(&newy, idelta))
1513  return NULL;
1514  leapdays = leaps_thru_end_of(newy - 1) -
1515  leaps_thru_end_of(y - 1);
1516  tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1517  tdays -= leapdays;
1518  y = newy;
1519  }
1520  {
1521  long seconds;
1522 
1523  seconds = tdays * SECSPERDAY + 0.5;
1524  tdays = seconds / SECSPERDAY;
1525  rem += seconds - tdays * SECSPERDAY;
1526  }
1527  /*
1528  ** Given the range, we can now fearlessly cast...
1529  */
1530  idays = tdays;
1531  rem += offset - corr;
1532  while (rem < 0) {
1533  rem += SECSPERDAY;
1534  --idays;
1535  }
1536  while (rem >= SECSPERDAY) {
1537  rem -= SECSPERDAY;
1538  ++idays;
1539  }
1540  while (idays < 0) {
1541  if (increment_overflow(&y, -1))
1542  return NULL;
1543  idays += year_lengths[isleap(y)];
1544  }
1545  while (idays >= year_lengths[isleap(y)]) {
1546  idays -= year_lengths[isleap(y)];
1547  // if (increment_overflow(&y, 1)) // commented-out because of nasty g++ -Wall comment
1548  // return NULL;
1549  }
1550  tmp->tm_year = y;
1551  // if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) // commented-out because of nasty g++ -Wall comment
1552  // return NULL;
1553  tmp->tm_yday = idays;
1554  /*
1555  ** The "extra" mods below avoid overflow problems.
1556  */
1557  tmp->tm_wday = EPOCH_WDAY +
1558  ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1560  leaps_thru_end_of(y - 1) -
1562  idays;
1563  tmp->tm_wday %= DAYSPERWEEK;
1564  if (tmp->tm_wday < 0)
1565  tmp->tm_wday += DAYSPERWEEK;
1566  tmp->tm_hour = (int) (rem / SECSPERHOUR);
1567  rem %= SECSPERHOUR;
1568  tmp->tm_min = (int) (rem / SECSPERMIN);
1569  /*
1570  ** A positive leap second requires a special
1571  ** representation. This uses "... ??:59:60" et seq.
1572  */
1573  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1574  ip = mon_lengths[isleap(y)];
1575  for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1576  idays -= ip[tmp->tm_mon];
1577  tmp->tm_mday = (int) (idays + 1);
1578  tmp->tm_isdst = 0;
1579 #ifdef TM_GMTOFF
1580  tmp->TM_GMTOFF = offset;
1581 #endif /* defined TM_GMTOFF */
1582  return tmp;
1583  }
1584 
1585  static void gmtload(struct state * const sp) {
1586  if (tzload(gmt, sp, TRUE) != 0)
1587  (void) tzparse(gmt, sp, TRUE);
1588  }
1589 
1590  static struct tm * gmtsub(const time_t * const timep, const long offset, struct tm * const tmp) {
1591  struct tm * result;
1592 
1593  if (!gmt_is_set) {
1594  gmt_is_set = TRUE;
1595  gmtload(gmtptr);
1596  }
1597  result = timesub(timep, offset, gmtptr, tmp);
1598  return result;
1599  }
1600 
1601  static struct tm * gmtime_(const time_t * const timep) {
1602  return gmtsub(timep, 0L, &tm);
1603  }
1604 }