Rcpp Version 1.0.14
Loading...
Searching...
No Matches
date.cpp
Go to the documentation of this file.
1// Date.cpp: Rcpp R/C++ interface class library -- Date type
2//
3// Copyright (C) 2010 - 2023 Dirk Eddelbuettel and Romain Francois
4//
5// The mktime00() as well as the gmtime_() replacement function are
6// Copyright (C) 2000 - 2010 The R Development Core Team.
7//
8// gmtime_() etc are from the public domain timezone code dated
9// 1996-06-05 by Arthur David Olson.
10//
11// This file is part of Rcpp.
12//
13// Rcpp is free software: you can redistribute it and/or modify it
14// under the terms of the GNU General Public License as published by
15// the Free Software Foundation, either version 2 of the License, or
16// (at your option) any later version.
17//
18// Rcpp is distributed in the hope that it will be useful, but
19// WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
25
26#define COMPILING_RCPP
27
28#include <R_ext/Boolean.h> // for TRUE,FALSE
29#include <Rcpp.h>
30#include <time.h> // for gmtime
31#include <Rcpp/exceptions.h>
32
33namespace Rcpp {
34
35 // Taken (in 2010) from R's src/main/datetime.c and made a member function called with C++ reference
36 // Later, R added the following comment we now (in 2016) add
37
38 /*
39
40 There are two implementation paths here.
41
42 1) Use the system functions for mktime, gmtime[_r], localtime[_r], strftime.
43 Use the system time_t, struct tm and time-zone tables.
44
45 2) Use substitutes from src/extra/tzone for mktime, gmtime, localtime,
46 strftime with a R_ prefix. The system strftime is used for
47 locale-dependent names in R_strptime and R_strftime. This uses the
48 time-zone tables shipped with R and installed into
49 R_HOME/share/zoneinfo .
50
51 Our own versions of time_t (64-bit) and struct tm (including the
52 BSD-style fields tm_zone and tm_gmtoff) are used.
53
54 For path 1), the system facilities are used for 1902-2037 and outside
55 those limits where there is a 64-bit time_t and the conversions work
56 (most OSes currently have only 32-bit time-zone tables). Otherwise
57 there is code below to extrapolate from 1902-2037.
58
59 Path 2) was added for R 3.1.0 and is the only one supported on
60 Windows: it is the default on macOS. The only currently (Jan 2014)
61 known OS with 64-bit time_t and complete tables is Linux.
62
63 */
64
65 // Now, R only ships share/zoneinfo on Windows AFAIK
66
67 /* Substitute for mktime -- no checking, always in GMT */
68
69 // [[Rcpp::register]]
70 double mktime00(struct tm &tm) {
71
72 static const int days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
73 static const int year_base = 1900;
74
75 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
76 #define days_in_year(year) (isleap(year) ? 366 : 365)
77
78 int day = 0;
79 int i, year, year0;
80 double excess = 0.0;
81
82 day = tm.tm_mday - 1;
83 year0 = year_base + tm.tm_year;
84 /* safety check for unbounded loops */
85 if (year0 > 3000) {
86 excess = (int)(year0/2000) - 1; // #nocov start
87 year0 -= (int)(excess * 2000);
88 } else if (year0 < 0) {
89 excess = -1 - (int)(-year0/2000);
90 year0 -= (int)(excess * 2000); // #nocov end
91 }
92
93 for(i = 0; i < tm.tm_mon; i++) day += days_in_month[i];
94 if (tm.tm_mon > 1 && isleap(year0)) day++;
95 tm.tm_yday = day;
96
97 if (year0 > 1970) {
98 for (year = 1970; year < year0; year++)
100 } else if (year0 < 1970) {
101 for (year = 1969; year >= year0; year--)
103 }
104
105 /* weekday: Epoch day was a Thursday */
106 if ((tm.tm_wday = (day + 4) % 7) < 0) tm.tm_wday += 7;
107
108 return tm.tm_sec + (tm.tm_min * 60) + (tm.tm_hour * 3600)
109 + (day + excess * 730485) * 86400.0;
110 }
111
112 #undef isleap
113 #undef days_in_year
114
115#include "sys/types.h" /* for time_t */
116#include "string.h"
117#include "limits.h" /* for CHAR_BIT et al. */
118
119#define _NO_OLDNAMES /* avoid tznames */
120#include "time.h"
121#undef _NO_OLDNAMES
122
123#include <errno.h>
124#ifndef EOVERFLOW
125# define EOVERFLOW 79
126#endif
127
128#include "stdlib.h"
129#include "stdint.h"
130#include "stdio.h"
131#include "fcntl.h"
132#include "float.h" /* for FLT_MAX and DBL_MAX */
133
134#include <unistd.h> // solaris needs this for read() and close()
135
136
137/* merged from private.h */
138#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
139#define TYPE_SIGNED(type) (((type) -1) < 0)
140#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
141#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
142#define GRANDPARENTED "Local time zone must be set--see zic manual page"
143#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
144#define AVGSECSPERYEAR 31556952L
145#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
146#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
147#define is_digit(c) ((unsigned)(c) - '0' <= 9)
148#define INITIALIZE(x) (x = 0)
149
150/* Max and min values of the integer type T, of which only the bottom
151 B bits are used, and where the highest-order used bit is considered
152 to be a sign bit if T is signed. */
153#define MAXVAL(t, b) \
154 ((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t))) \
155 - 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
156#define MINVAL(t, b) \
157 ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
158
159/* The minimum and maximum finite time values. This assumes no padding. */
162
163 //#include "tzfile.h" // from src/extra/tzone/tzfile.h
164 // BEGIN ------------------------------------------------------------------------------------------ tzfile.h
165#ifndef TZFILE_H
166
167#define TZFILE_H
168
169/*
170** This file is in the public domain, so clarified as of
171** 1996-06-05 by Arthur David Olson.
172*/
173
174/*
175** This header is for use ONLY with the time conversion code.
176** There is no guarantee that it will remain unchanged,
177** or that it will remain at all.
178** Do NOT copy it to any system include directory.
179** Thank you!
180*/
181
182/*
183** Information about time zone files.
184*/
185
186#ifndef TZDIR
187#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */
188#endif /* !defined TZDIR */
189
190#ifndef TZDEFAULT
191#define TZDEFAULT "localtime" // NB this is "UTC" in R, but R also loads tz data
192#endif /* !defined TZDEFAULT */
193
194#ifndef TZDEFRULES
195#define TZDEFRULES "America/New_York"
196#endif /* !defined TZDEFRULES */
197
198/*
199** Each file begins with. . .
200*/
201
202#define TZ_MAGIC "TZif"
203
204struct tzhead {
205 char tzh_magic[4]; /* TZ_MAGIC */
206 char tzh_version[1]; /* '\0' or '2' as of 2005 */
207 char tzh_reserved[15]; /* reserved--must be zero */
208 char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
209 char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
210 char tzh_leapcnt[4]; /* coded number of leap seconds */
211 char tzh_timecnt[4]; /* coded number of transition times */
212 char tzh_typecnt[4]; /* coded number of local time types */
213 char tzh_charcnt[4]; /* coded number of abbr. chars */
214};
215
216/*
217** . . .followed by. . .
218**
219** tzh_timecnt (char [4])s coded transition times a la time(2)
220** tzh_timecnt (unsigned char)s types of local time starting at above
221** tzh_typecnt repetitions of
222** one (char [4]) coded UTC offset in seconds
223** one (unsigned char) used to set tm_isdst
224** one (unsigned char) that's an abbreviation list index
225** tzh_charcnt (char)s '\0'-terminated zone abbreviations
226** tzh_leapcnt repetitions of
227** one (char [4]) coded leap second transition times
228** one (char [4]) total correction after above
229** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
230** time is standard time, if FALSE,
231** transition time is wall clock time
232** if absent, transition times are
233** assumed to be wall clock time
234** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
235** time is UTC, if FALSE,
236** transition time is local time
237** if absent, transition times are
238** assumed to be local time
239*/
240
241/*
242** If tzh_version is '2' or greater, the above is followed by a second instance
243** of tzhead and a second instance of the data in which each coded transition
244** time uses 8 rather than 4 chars,
245** then a POSIX-TZ-environment-variable-style string for use in handling
246** instants after the last transition time stored in the file
247** (with nothing between the newlines if there is no POSIX representation for
248** such instants).
249**
250** If tz_version is '3' or greater, the above is extended as follows.
251** First, the POSIX TZ string's hour offset may range from -167
252** through 167 as compared to the POSIX-required 0 through 24.
253** Second, its DST start time may be January 1 at 00:00 and its stop
254** time December 31 at 24:00 plus the difference between DST and
255** standard time, indicating DST all year.
256*/
257
258/*
259** In the current implementation, "tzset()" refuses to deal with files that
260** exceed any of the limits below.
261*/
262
263#ifndef TZ_MAX_TIMES
264#define TZ_MAX_TIMES 1200
265#endif /* !defined TZ_MAX_TIMES */
266
267#ifndef TZ_MAX_TYPES
268#ifndef NOSOLAR
269#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
270#endif /* !defined NOSOLAR */
271#ifdef NOSOLAR
272/*
273** Must be at least 14 for Europe/Riga as of Jan 12 1995,
274** as noted by Earl Chew.
275*/
276#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
277#endif /* !defined NOSOLAR */
278#endif /* !defined TZ_MAX_TYPES */
279
280// increased from 50, http://mm.icann.org/pipermail/tz/2015-August/022623.html
281#ifndef TZ_MAX_CHARS
282#define TZ_MAX_CHARS 100 /* Maximum number of abbreviation characters */
283 /* (limited by what unsigned chars can hold) */
284#endif /* !defined TZ_MAX_CHARS */
285
286#ifndef TZ_MAX_LEAPS
287#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
288#endif /* !defined TZ_MAX_LEAPS */
289
290#define SECSPERMIN 60
291#define MINSPERHOUR 60
292#define HOURSPERDAY 24
293#define DAYSPERWEEK 7
294#define DAYSPERNYEAR 365
295#define DAYSPERLYEAR 366
296#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
297#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
298#define MONSPERYEAR 12
299
300#define TM_SUNDAY 0
301#define TM_MONDAY 1
302#define TM_TUESDAY 2
303#define TM_WEDNESDAY 3
304#define TM_THURSDAY 4
305#define TM_FRIDAY 5
306#define TM_SATURDAY 6
307
308#define TM_JANUARY 0
309#define TM_FEBRUARY 1
310#define TM_MARCH 2
311#define TM_APRIL 3
312#define TM_MAY 4
313#define TM_JUNE 5
314#define TM_JULY 6
315#define TM_AUGUST 7
316#define TM_SEPTEMBER 8
317#define TM_OCTOBER 9
318#define TM_NOVEMBER 10
319#define TM_DECEMBER 11
320
321#define TM_YEAR_BASE 1900
322
323#define EPOCH_YEAR 1970
324#define EPOCH_WDAY TM_THURSDAY
325
326#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
327
328/*
329** Since everything in isleap is modulo 400 (or a factor of 400), we know that
330** isleap(y) == isleap(y % 400)
331** and so
332** isleap(a + b) == isleap((a + b) % 400)
333** or
334** isleap(a + b) == isleap(a % 400 + b % 400)
335** This is true even if % means modulo rather than Fortran remainder
336** (which is allowed by C89 but not C99).
337** We use this to avoid addition overflow problems.
338*/
339
340#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
341
342#endif /* !defined TZFILE_H */
343
344 // -------------------------------------------------------------------------------------- END tzfile.h
345
346 //#include "localtime.c" // from src/extra/tzone/localtime.c
347 // note though that was included is partial as we support only gmtime_()
348 // BEGIN --------------------------------------------------------------------------------- localtime.c
349
350#ifdef O_BINARY
351#define OPEN_MODE (O_RDONLY | O_BINARY)
352#endif /* defined O_BINARY */
353#ifndef O_BINARY
354#define OPEN_MODE O_RDONLY
355#endif /* !defined O_BINARY */
356
357 static const char gmt[] = "GMT";
358
359 /*
360 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
361 ** We default to US rules as of 1999-08-17.
362 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
363 ** implementation dependent; for historical reasons, US rules are a
364 ** common default.
365 */
366#ifndef TZDEFRULESTRING
367#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
368#endif /* !defined TZDEFDST */
369
370#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
371
372#ifdef TZNAME_MAX
373#define MY_TZNAME_MAX TZNAME_MAX
374#endif /* defined TZNAME_MAX */
375#ifndef TZNAME_MAX
376#define MY_TZNAME_MAX 255
377#endif /* !defined TZNAME_MAX */
378
379 struct ttinfo { /* time type information */
380 int_fast32_t tt_gmtoff; /* UTC offset in seconds */
381 int tt_isdst; /* used to set tm_isdst */
382 int tt_abbrind; /* abbreviation list index */
383 int tt_ttisstd; /* TRUE if transition is std time */
384 int tt_ttisgmt; /* TRUE if transition is UTC */
385 };
386
387 struct lsinfo { /* leap second information */
388 time_t ls_trans; /* transition time */
389 int_fast64_t ls_corr; /* correction to apply */
390 };
391
406
407 struct rule {
408 int r_type; /* type of rule--see below */
409 int r_day; /* day number of rule */
410 int r_week; /* week number of rule */
411 int r_mon; /* month number of rule */
412 int_fast32_t r_time; /* transition time of rule */
413 };
414
415#define JULIAN_DAY 0 /* Jn - Julian day */
416#define DAY_OF_YEAR 1 /* n - day of year */
417#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
418
419 static const int mon_lengths[2][MONSPERYEAR] = {
420 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
421 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
422 };
423
424 static const int year_lengths[2] = {
426 };
427
428 static int gmt_is_set;
429
430 //static struct state lclmem;
431 static struct state gmtmem;
432 //#define lclptr (&lclmem)
433#define gmtptr (&gmtmem)
434
435 static struct tm tm;
436
437 //extern const char *getTZinfo(void);
438
439 static int tzparse(const char * name, struct state * sp, int lastditch);
440 static int typesequiv(const struct state * sp, int a, int b);
441 static const char * getsecs(const char * strp, int_fast32_t * secsp);
442 static const char * getnum(const char * strp, int * const nump, const int min, const int max);
443 static const char * getrule(const char * strp, struct rule * const rulep);
444 static int_fast32_t transtime(int year, const struct rule * rulep, int_fast32_t offset);
445 static struct tm * timesub(const time_t *timep, int_fast32_t offset, const struct state *sp, struct tm *tmp);
446 static int leaps_thru_end_of(const int y);
447
448 /*
449 ** Normalize logic courtesy Paul Eggert.
450 */
451
452 static int increment_overflow(int *const ip, int j) {
453 int const i = *ip;
454
455 /*
456 ** If i >= 0 there can only be overflow if i + j > INT_MAX
457 ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
458 ** If i < 0 there can only be overflow if i + j < INT_MIN
459 ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
460 */
461 if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
462 return TRUE; // #nocov
463 *ip += j;
464 return FALSE;
465 }
466
467 static int increment_overflow_time(time_t *tp, int_fast32_t j) { // #nocov start
468 /*
469 ** This is like
470 ** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
471 ** except that it does the right thing even if *tp + j would overflow.
472 */
473 if (! (j < 0
474 ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
475 : *tp <= time_t_max - j))
476 return TRUE;
477 *tp += j;
478 return FALSE;
479 }
480
481 static int_fast32_t detzcode(const char *const codep) {
482 int_fast32_t result = (codep[0] & 0x80) ? -1 : 0;
483 for (int i = 0; i < 4; ++i)
484 result = (result << 8) | (codep[i] & 0xff);
485 return result;
486 }
487
488 static int_fast64_t detzcode64(const char *const codep) {
489 int_fast64_t result = (codep[0] & 0x80) ? -1 : 0;
490 for (int i = 0; i < 8; ++i)
491 result = (result << 8) | (codep[i] & 0xff);
492 return result;
493 }
494
495 static int differ_by_repeat(const time_t t1, const time_t t0) {
496 if (TYPE_INTEGRAL(time_t) &&
498 return 0;
499 /* R change */
501 }
502
503 static const char * getzname(const char * strp) {
504 char c;
505
506 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
507 c != '+')
508 ++strp;
509 return strp;
510 }
511
512 static const char * getqzname(const char *strp, const int delim) {
513 int c;
514
515 while ((c = *strp) != '\0' && c != delim)
516 ++strp;
517 return strp;
518 }
519
520 static const char * getoffset(const char *strp, int_fast32_t *const offsetp) {
521 int neg = 0;
522
523 if (*strp == '-') {
524 neg = 1;
525 ++strp;
526 } else if (*strp == '+')
527 ++strp;
529 if (strp == NULL)
530 return NULL; /* illegal time */
531 if (neg)
532 *offsetp = -*offsetp;
533 return strp;
534 }
535
536 static const char * getsecs(const char *strp, int_fast32_t *const secsp) {
537 int num;
538
539 /*
540 ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
541 ** "M10.4.6/26", which does not conform to Posix,
542 ** but which specifies the equivalent of
543 ** "02:00 on the first Sunday on or after 23 Oct".
544 */
545 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
546 if (strp == NULL)
547 return NULL;
549 if (*strp == ':') {
550 ++strp;
551 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
552 if (strp == NULL)
553 return NULL;
554 *secsp += num * SECSPERMIN;
555 if (*strp == ':') {
556 ++strp;
557 /* 'SECSPERMIN' allows for leap seconds. */
558 strp = getnum(strp, &num, 0, SECSPERMIN);
559 if (strp == NULL)
560 return NULL;
561 *secsp += num;
562 }
563 }
564 return strp;
565 }
566
567 static const char * getnum(const char * strp, int * const nump, const int min, const int max) {
568 char c;
569 int num;
570
571 if (strp == NULL || !is_digit(c = *strp))
572 return NULL;
573 num = 0;
574 do {
575 num = num * 10 + (c - '0');
576 if (num > max)
577 return NULL; /* illegal value */
578 c = *++strp;
579 } while (is_digit(c));
580 if (num < min)
581 return NULL; /* illegal value */
582 *nump = num;
583 return strp;
584 }
585
586 static const char * getrule(const char * strp, struct rule * const rulep) {
587 if (*strp == 'J') {
588 /*
589 ** Julian day.
590 */
591 rulep->r_type = JULIAN_DAY;
592 ++strp;
593 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
594 } else if (*strp == 'M') {
595 /*
596 ** Month, week, day.
597 */
599 ++strp;
600 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
601 if (strp == NULL)
602 return NULL;
603 if (*strp++ != '.')
604 return NULL;
605 strp = getnum(strp, &rulep->r_week, 1, 5);
606 if (strp == NULL)
607 return NULL;
608 if (*strp++ != '.')
609 return NULL;
610 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
611 } else if (is_digit(*strp)) {
612 /*
613 ** Day of year.
614 */
615 rulep->r_type = DAY_OF_YEAR;
616 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
617 } else return NULL; /* invalid format */
618 if (strp == NULL)
619 return NULL;
620 if (*strp == '/') {
621 /*
622 ** Time specified.
623 */
624 ++strp;
625 strp = getsecs(strp, &rulep->r_time);
626 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
627 return strp;
628 }
629
630 // this routine modified / simplified / reduced in 2010
631 static int tzload(const char * name, struct state * const sp, const int doextend) {
632 const char * p;
633 int i;
634 int fid;
635 int stored;
636 int nread;
637 union {
638 struct tzhead tzhead;
639 char buf[2 * sizeof(struct tzhead) +
640 2 * sizeof *sp + 4 * TZ_MAX_TIMES];
641 } u;
642
643 sp->goback = sp->goahead = FALSE;
644 /* if (name == NULL && (name = TZDEFAULT) == NULL) return -1; */
645 if (name == NULL) {
646 // edd 06 Jul 2010 let's do without getTZinfo()
647 //name = getTZinfo();
648 //if( strcmp(name, "unknown") == 0 ) name = TZDEFAULT;
649 name = TZDEFAULT;
650 }
651
652 {
653 int doaccess;
654 /*
655 ** Section 4.9.1 of the C standard says that
656 ** "FILENAME_MAX expands to an integral constant expression
657 ** that is the size needed for an array of char large enough
658 ** to hold the longest file name string that the implementation
659 ** guarantees can be opened."
660 */
661 char fullname[FILENAME_MAX + 1];
662 // edd 08 Jul 2010 not currently needed const char *sname = name;
663
664 if (name[0] == ':')
665 ++name;
666 doaccess = name[0] == '/';
667 if (!doaccess) {
668 char buf[1000];
669 p = getenv("TZDIR");
670 if (p == NULL) {
671 snprintf(buf, 1000, "%s/share/zoneinfo",
672 getenv("R_HOME"));
673 buf[999] = '\0';
674 p = buf;
675 }
676 /* if ((p = TZDIR) == NULL) return -1; */
677 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
678 return -1;
679 (void) strcpy(fullname, p);
680 (void) strcat(fullname, "/");
681 (void) strcat(fullname, name);
682 /*
683 ** Set doaccess if '.' (as in "../") shows up in name.
684 */
685 if (strchr(name, '.') != NULL) doaccess = TRUE;
686 name = fullname;
687 }
688 // edd 16 Jul 2010 comment out whole block
689 //if (doaccess && access(name, R_OK) != 0) {
690 // edd 08 Jul 2010 we use this without TZ for dates only
691 // so no need to warn
692 //Rf_warning("unknown timezone '%s'", sname);
693 //return -1;
694 //}
695 if ((fid = open(name, OPEN_MODE)) == -1) {
696 // edd 08 Jul 2010 we use this without TZ for dates only
697 // so no need to warn
698 //Rf_warning("unknown timezone '%s'", sname);
699 return -1;
700 }
701
702 }
703 nread = (int)read(fid, u.buf, sizeof u.buf);
704 if (close(fid) < 0 || nread <= 0)
705 return -1;
706 for (stored = 4; stored <= 8; stored *= 2) {
707 int ttisstdcnt;
708 int ttisgmtcnt;
709
710 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
711 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
712 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
713 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
714 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
715 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
716 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
717 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
718 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
719 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
720 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
721 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
722 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
723 return -1;
724 if (nread - (p - u.buf) <
725 sp->timecnt * stored + /* ats */
726 sp->timecnt + /* types */
727 sp->typecnt * 6 + /* ttinfos */
728 sp->charcnt + /* chars */
729 sp->leapcnt * (stored + 4) + /* lsinfos */
730 ttisstdcnt + /* ttisstds */
731 ttisgmtcnt) /* ttisgmts */
732 return -1;
733 for (i = 0; i < sp->timecnt; ++i) {
734 sp->ats[i] = (stored == 4) ? detzcode(p) : detzcode64(p);
735 p += stored;
736 }
737 for (i = 0; i < sp->timecnt; ++i) {
738 sp->types[i] = (unsigned char) *p++;
739 if (sp->types[i] >= sp->typecnt)
740 return -1;
741 }
742 for (i = 0; i < sp->typecnt; ++i) {
743 struct ttinfo * ttisp;
744
745 ttisp = &sp->ttis[i];
747 p += 4;
748 ttisp->tt_isdst = (unsigned char) *p++;
749 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
750 return -1;
751 ttisp->tt_abbrind = (unsigned char) *p++;
752 if (ttisp->tt_abbrind < 0 ||
753 ttisp->tt_abbrind > sp->charcnt)
754 return -1;
755 }
756 for (i = 0; i < sp->charcnt; ++i)
757 sp->chars[i] = *p++;
758 sp->chars[i] = '\0'; /* ensure '\0' at end */
759 for (i = 0; i < sp->leapcnt; ++i) {
760 struct lsinfo * lsisp;
761
762 lsisp = &sp->lsis[i];
763 lsisp->ls_trans = (stored == 4) ? detzcode(p) : detzcode64(p);
764 p += stored;
765 lsisp->ls_corr = detzcode(p);
766 p += 4;
767 }
768 for (i = 0; i < sp->typecnt; ++i) {
769 struct ttinfo * ttisp;
770
771 ttisp = &sp->ttis[i];
772 if (ttisstdcnt == 0)
774 else {
775 ttisp->tt_ttisstd = *p++;
776 if (ttisp->tt_ttisstd != TRUE && ttisp->tt_ttisstd != FALSE)
777 return -1;
778 }
779 }
780 for (i = 0; i < sp->typecnt; ++i) {
781 struct ttinfo * ttisp;
782
783 ttisp = &sp->ttis[i];
784 if (ttisgmtcnt == 0)
786 else {
787 ttisp->tt_ttisgmt = *p++;
788 if (ttisp->tt_ttisgmt != TRUE && ttisp->tt_ttisgmt != FALSE)
789 return -1;
790 }
791 }
792 /*
793 ** Out-of-sort ats should mean we're running on a
794 ** signed time_t system but using a data file with
795 ** unsigned values (or vice versa).
796 */
797 for (i = 0; i < sp->timecnt - 2; ++i)
798 if (sp->ats[i] > sp->ats[i + 1]) {
799 ++i;
800 if (TYPE_SIGNED(time_t)) {
801 /*
802 ** Ignore the end (easy).
803 */
804 sp->timecnt = i;
805 } else {
806 /*
807 ** Ignore the beginning (harder).
808 */
809 int j;
810
811 for (j = 0; j + i < sp->timecnt; ++j) {
812 sp->ats[j] = sp->ats[j + i];
813 sp->types[j] = sp->types[j + i];
814 }
815 sp->timecnt = j;
816 }
817 break;
818 }
819 /*
820 ** If this is an old file, we're done.
821 */
822 if (u.tzhead.tzh_version[0] == '\0')
823 break;
824 nread -= p - u.buf;
825 for (i = 0; i < nread; ++i)
826 u.buf[i] = p[i];
827 /*
828 ** If this is a narrow integer time_t system, we're done.
829 */
830 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
831 break;
832 }
833 if (doextend && nread > 2 &&
834 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
835 sp->typecnt + 2 <= TZ_MAX_TYPES) {
836 struct state ts;
837 int result;
838
839 u.buf[nread - 1] = '\0';
840 result = tzparse(&u.buf[1], &ts, FALSE);
841 if (result == 0 && ts.typecnt == 2 &&
842 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
843 for (i = 0; i < 2; ++i)
844 ts.ttis[i].tt_abbrind += sp->charcnt;
845 for (i = 0; i < ts.charcnt; ++i)
846 sp->chars[sp->charcnt++] = ts.chars[i];
847 i = 0;
848 while (i < ts.timecnt && ts.ats[i] <= sp->ats[sp->timecnt - 1])
849 ++i;
850 while (i < ts.timecnt &&
851 sp->timecnt < TZ_MAX_TIMES) {
852 sp->ats[sp->timecnt] = ts.ats[i];
853 sp->types[sp->timecnt] = (unsigned char)sp->typecnt + ts.types[i];
854 ++sp->timecnt;
855 ++i;
856 }
857 sp->ttis[sp->typecnt++] = ts.ttis[0];
858 sp->ttis[sp->typecnt++] = ts.ttis[1];
859 }
860 }
861 i = 2 * YEARSPERREPEAT;
862 sp->goback = sp->goahead = sp->timecnt > i;
863 sp->goback = sp->goback &&
864 typesequiv(sp, sp->types[i], sp->types[0]) &&
865 differ_by_repeat(sp->ats[i], sp->ats[0]);
866 sp->goahead = sp->goahead &&
867 typesequiv(sp, sp->types[sp->timecnt - 1],
868 sp->types[sp->timecnt - 1 - i]) &&
869 differ_by_repeat(sp->ats[sp->timecnt - 1],
870 sp->ats[sp->timecnt - 1 - i]);
871 return 0;
872 }
873
874 /*
875 ** Given a year, a rule, and the offset from UT at the time that rule takes
876 ** effect, calculate the year-relative time that rule takes effect.
877 */
878 static int_fast32_t transtime(const int year, const struct rule *const rulep, const int_fast32_t offset) {
879 int leapyear;
880 int_fast32_t value;
881 int d, m1, yy0, yy1, yy2, dow;
882
883 INITIALIZE(value);
885 switch (rulep->r_type) {
886
887 case JULIAN_DAY:
888 /*
889 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
890 ** years.
891 ** In non-leap years, or if the day number is 59 or less, just
892 ** add SECSPERDAY times the day number-1 to the time of
893 ** January 1, midnight, to get the day.
894 */
895 value = (rulep->r_day - 1) * SECSPERDAY;
896 if (leapyear && rulep->r_day >= 60)
897 value += SECSPERDAY;
898 break;
899
900 case DAY_OF_YEAR:
901 /*
902 ** n - day of year.
903 ** Just add SECSPERDAY times the day number to the time of
904 ** January 1, midnight, to get the day.
905 */
906 value = rulep->r_day * SECSPERDAY;
907 break;
908
910 /*
911 ** Mm.n.d - nth "dth day" of month m.
912 */
913
914 /*
915 ** Use Zeller's Congruence to get day-of-week of first day of
916 ** month.
917 */
918 m1 = (rulep->r_mon + 9) % 12 + 1;
919 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
920 yy1 = yy0 / 100;
921 yy2 = yy0 % 100;
922 dow = ((26 * m1 - 2) / 10 +
923 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
924 if (dow < 0)
925 dow += DAYSPERWEEK;
926
927 /*
928 ** "dow" is the day-of-week of the first day of the month. Get
929 ** the day-of-month (zero-origin) of the first "dow" day of the
930 ** month.
931 */
932 d = rulep->r_day - dow;
933 if (d < 0)
934 d += DAYSPERWEEK;
935 for (int i = 1; i < rulep->r_week; ++i) {
936 if (d + DAYSPERWEEK >=
937 mon_lengths[leapyear][rulep->r_mon - 1])
938 break;
939 d += DAYSPERWEEK;
940 }
941
942 /*
943 ** "d" is the day-of-month (zero-origin) of the day we want.
944 */
945 value = d * SECSPERDAY;
946 for (int i = 0; i < rulep->r_mon - 1; ++i)
947 value += mon_lengths[leapyear][i] * SECSPERDAY;
948 break;
949 }
950
951 /*
952 ** "value" is the year-relative time of 00:00:00 UT on the day in
953 ** question. To get the year-relative time of the specified local
954 ** time on that day, add the transition time and the current offset
955 ** from UT.
956 */
957 return value + rulep->r_time + offset;
958 }
959
960 /*
961 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
962 ** appropriate.
963 */
964
965 static int tzparse(const char * name, struct state * const sp, const int lastditch) {
966 const char * stdname;
967 const char * dstname;
968 size_t stdlen;
969 size_t dstlen;
972 char * cp;
973 int load_result;
974 static struct ttinfo zttinfo;
975
977 stdname = name;
978 if (lastditch) {
979 stdlen = strlen(name); /* length of standard zone name */
980 name += stdlen;
981 if (stdlen >= sizeof sp->chars)
982 stdlen = (sizeof sp->chars) - 1;
983 stdoffset = 0;
984 } else {
985 if (*name == '<') {
986 name++;
987 stdname = name;
988 name = getqzname(name, '>');
989 if (*name != '>')
990 return (-1);
991 stdlen = name - stdname;
992 name++;
993 } else {
994 name = getzname(name);
995 stdlen = name - stdname;
996 }
997 if (*name == '\0')
998 return -1;
999 name = getoffset(name, &stdoffset);
1000 if (name == NULL)
1001 return -1;
1002 }
1004 if (load_result != 0)
1005 sp->leapcnt = 0; /* so, we're off a little */
1006 if (*name != '\0') {
1007 if (*name == '<') {
1008 dstname = ++name;
1009 name = getqzname(name, '>');
1010 if (*name != '>')
1011 return -1;
1012 dstlen = name - dstname;
1013 name++;
1014 } else {
1015 dstname = name;
1016 name = getzname(name);
1017 dstlen = name - dstname; /* length of DST zone name */
1018 }
1019 if (*name != '\0' && *name != ',' && *name != ';') {
1020 name = getoffset(name, &dstoffset);
1021 if (name == NULL)
1022 return -1;
1023 } else dstoffset = stdoffset - SECSPERHOUR;
1024 if (*name == '\0' && load_result != 0)
1025 name = TZDEFRULESTRING;
1026 if (*name == ',' || *name == ';') {
1027 struct rule start;
1028 struct rule end;
1029 int year;
1030 int yearlim;
1031 int timecnt;
1033
1034 ++name;
1035 if ((name = getrule(name, &start)) == NULL)
1036 return -1;
1037 if (*name++ != ',')
1038 return -1;
1039 if ((name = getrule(name, &end)) == NULL)
1040 return -1;
1041 if (*name != '\0')
1042 return -1;
1043 sp->typecnt = 2; /* standard time and DST */
1044 /*
1045 ** Two transitions per year, from EPOCH_YEAR forward.
1046 */
1047 sp->ttis[0] = sp->ttis[1] = zttinfo;
1048 sp->ttis[0].tt_gmtoff = -dstoffset;
1049 sp->ttis[0].tt_isdst = 1;
1050 sp->ttis[0].tt_abbrind = (int)(stdlen + 1);
1051 sp->ttis[1].tt_gmtoff = -stdoffset;
1052 sp->ttis[1].tt_isdst = 0;
1053 sp->ttis[1].tt_abbrind = 0;
1054 timecnt = 0;
1055 janfirst = 0;
1057 for (year = EPOCH_YEAR; year < yearlim; year++) {
1059 starttime = transtime(year, &start, stdoffset),
1060 endtime = transtime(year, &end, dstoffset);
1063 * SECSPERDAY);
1064 int reversed = endtime < starttime;
1065 if (reversed) {
1066 int_fast32_t swap = starttime;
1068 endtime = swap;
1069 }
1070 if (reversed
1071 || (starttime < endtime
1072 && (endtime - starttime
1073 < (yearsecs
1074 + (stdoffset - dstoffset))))) {
1075 if (TZ_MAX_TIMES - 2 < timecnt)
1076 break;
1077 yearlim = year + YEARSPERREPEAT + 1;
1078 sp->ats[timecnt] = janfirst;
1080 (&sp->ats[timecnt], starttime))
1081 break;
1082 sp->types[timecnt++] = (unsigned char) reversed;
1083 sp->ats[timecnt] = janfirst;
1085 (&sp->ats[timecnt], endtime))
1086 break;
1087 sp->types[timecnt++] = !reversed;
1088 }
1090 break;
1091 }
1092 sp->timecnt = timecnt;
1093 if (!timecnt)
1094 sp->typecnt = 1; /* Perpetual DST. */
1095 } else {
1097 int isdst;
1098
1099 if (*name != '\0')
1100 return -1;
1101 /*
1102 ** Initial values of theirstdoffset and theirdstoffset.
1103 */
1104 theirstdoffset = 0;
1105 for (int i = 0; i < sp->timecnt; ++i) {
1106 int j = sp->types[i];
1107 if (!sp->ttis[j].tt_isdst) {
1109 -sp->ttis[j].tt_gmtoff;
1110 break;
1111 }
1112 }
1113 theirdstoffset = 0;
1114 for (int i = 0; i < sp->timecnt; ++i) {
1115 int j = sp->types[i];
1116 if (sp->ttis[j].tt_isdst) {
1118 -sp->ttis[j].tt_gmtoff;
1119 break;
1120 }
1121 }
1122 /*
1123 ** Initially we're assumed to be in standard time.
1124 */
1125 isdst = FALSE;
1127 /*
1128 ** Now juggle transition times and types
1129 ** tracking offsets as you do.
1130 */
1131 for (int i = 0; i < sp->timecnt; ++i) {
1132 int j = sp->types[i];
1133 sp->types[i] = (unsigned char)sp->ttis[j].tt_isdst;
1134 if (sp->ttis[j].tt_ttisgmt) {
1135 /* No adjustment to transition time */
1136 } else {
1137 /*
1138 ** If summer time is in effect, and the
1139 ** transition time was not specified as
1140 ** standard time, add the summer time
1141 ** offset to the transition time;
1142 ** otherwise, add the standard time
1143 ** offset to the transition time.
1144 */
1145 /*
1146 ** Transitions from DST to DDST
1147 ** will effectively disappear since
1148 ** POSIX provides for only one DST
1149 ** offset.
1150 */
1151 if (isdst && !sp->ttis[j].tt_ttisstd) {
1152 sp->ats[i] += dstoffset -
1154 } else {
1155 sp->ats[i] += stdoffset -
1157 }
1158 }
1159 theiroffset = -sp->ttis[j].tt_gmtoff;
1160 if (sp->ttis[j].tt_isdst)
1163 }
1164 /*
1165 ** Finally, fill in ttis.
1166 */
1167 sp->ttis[0] = sp->ttis[1] = zttinfo;
1168 sp->ttis[0].tt_gmtoff = -stdoffset;
1169 sp->ttis[0].tt_isdst = FALSE;
1170 sp->ttis[0].tt_abbrind = 0;
1171 sp->ttis[1].tt_gmtoff = -dstoffset;
1172 sp->ttis[1].tt_isdst = TRUE;
1173 sp->ttis[1].tt_abbrind = (int)(stdlen + 1);
1174 sp->typecnt = 2;
1175 }
1176 } else {
1177 dstlen = 0;
1178 sp->typecnt = 1; /* only standard time */
1179 sp->timecnt = 0;
1180 sp->ttis[0] = zttinfo;
1181 sp->ttis[0].tt_gmtoff = -stdoffset;
1182 sp->ttis[0].tt_isdst = 0;
1183 sp->ttis[0].tt_abbrind = 0;
1184 }
1185 sp->charcnt = (int)(stdlen + 1);
1186 if (dstlen != 0)
1187 sp->charcnt += dstlen + 1;
1188 if ((size_t) sp->charcnt > sizeof sp->chars)
1189 return -1;
1190 cp = sp->chars;
1192 cp += stdlen;
1193 *cp++ = '\0';
1194 if (dstlen != 0) {
1196 *(cp + dstlen) = '\0';
1197 }
1198 return 0;
1199 }
1200
1201 static int typesequiv(const struct state * const sp, const int a, const int b) {
1202 int result;
1203
1204 if (sp == NULL ||
1205 a < 0 || a >= sp->typecnt ||
1206 b < 0 || b >= sp->typecnt)
1207 result = FALSE;
1208 else {
1209 const struct ttinfo * ap = &sp->ttis[a];
1210 const struct ttinfo * bp = &sp->ttis[b];
1211 result = ap->tt_gmtoff == bp->tt_gmtoff &&
1212 ap->tt_isdst == bp->tt_isdst &&
1213 ap->tt_ttisstd == bp->tt_ttisstd &&
1214 ap->tt_ttisgmt == bp->tt_ttisgmt &&
1215 strcmp(&sp->chars[ap->tt_abbrind],
1216 &sp->chars[bp->tt_abbrind]) == 0;
1217 }
1218 return result;
1219 } // #nocov end
1220
1221 static int leaps_thru_end_of(const int y) {
1222 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1223 -(leaps_thru_end_of(-(y + 1)) + 1);
1224 }
1225
1226 static struct tm * timesub(const time_t *const timep, const int_fast32_t offset,
1227 const struct state *const sp, struct tm *const tmp) {
1228 const struct lsinfo * lp;
1229 time_t tdays;
1230 int idays; /* unsigned would be so 2003 */
1232 int y;
1233 const int * ip;
1235 int hit;
1236 int i;
1237
1238 corr = 0;
1239 hit = 0;
1240 i = sp->leapcnt;
1241 while (--i >= 0) {
1242 lp = &sp->lsis[i]; // #nocov start
1243 if (*timep >= lp->ls_trans) {
1244 if (*timep == lp->ls_trans) {
1245 hit = ((i == 0 && lp->ls_corr > 0) ||
1246 lp->ls_corr > sp->lsis[i - 1].ls_corr);
1247 if (hit)
1248 while (i > 0 &&
1249 sp->lsis[i].ls_trans ==
1250 sp->lsis[i - 1].ls_trans + 1 &&
1251 sp->lsis[i].ls_corr ==
1252 sp->lsis[i - 1].ls_corr + 1) {
1253 ++hit;
1254 --i;
1255 }
1256 }
1257 corr = lp->ls_corr;
1258 break; // #nocov end
1259 }
1260 }
1261 y = EPOCH_YEAR;
1262 tdays = *timep / SECSPERDAY;
1263 rem = *timep - tdays * SECSPERDAY;
1265 int newy;
1266 time_t tdelta;
1267 int idelta;
1268 int leapdays;
1269
1271 if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
1272 && tdelta <= INT_MAX))
1273 return NULL; // #nocov
1274 idelta = (int)tdelta;
1275 if (idelta == 0)
1276 idelta = (tdays < 0) ? -1 : 1;
1277 newy = y;
1279 return NULL; // #nocov
1281 leaps_thru_end_of(y - 1);
1282 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1283 tdays -= leapdays;
1284 y = newy;
1285 }
1286 {
1288
1291 rem += seconds - tdays * SECSPERDAY;
1292 }
1293 /*
1294 ** Given the range, we can now fearlessly cast...
1295 */
1296 idays = (int)tdays;
1297 rem += offset - corr;
1298 while (rem < 0) { // #nocov start
1299 rem += SECSPERDAY;
1300 --idays;
1301 }
1302 while (rem >= SECSPERDAY) {
1303 rem -= SECSPERDAY;
1304 ++idays;
1305 }
1306 while (idays < 0) {
1307 if (increment_overflow(&y, -1))
1308 return NULL;
1309 idays += year_lengths[isleap(y)];
1310 }
1311 while (idays >= year_lengths[isleap(y)]) {
1312 idays -= year_lengths[isleap(y)];
1313 if (increment_overflow(&y, 1))
1314 return NULL; // #nocov end
1315 }
1316 // Previously we returned 'year + base', so keep behaviour
1317 // It seems like R now returns just 'year - 1900' (as libc does)
1318 // But better for continuity to do as before
1319 tmp->tm_year = y + TM_YEAR_BASE;
1320 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1321 return NULL; // #nocov
1322 tmp->tm_yday = idays;
1323 /*
1324 ** The "extra" mods below avoid overflow problems.
1325 */
1326 tmp->tm_wday = EPOCH_WDAY +
1327 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1329 leaps_thru_end_of(y - 1) -
1331 idays;
1332 tmp->tm_wday %= DAYSPERWEEK;
1333 if (tmp->tm_wday < 0)
1334 tmp->tm_wday += DAYSPERWEEK; // #nocov
1335 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1336 rem %= SECSPERHOUR;
1337 tmp->tm_min = (int) (rem / SECSPERMIN);
1338 /*
1339 ** A positive leap second requires a special
1340 ** representation. This uses "... ??:59:60" et seq.
1341 */
1342 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1343 ip = mon_lengths[isleap(y)];
1344 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1345 idays -= ip[tmp->tm_mon];
1346 tmp->tm_mday = (int) (idays + 1);
1347 tmp->tm_isdst = 0;
1348#if ! (defined(__MINGW32__) || defined(__MINGW64__) || defined(__sun) || defined(sun) || defined(_AIX))
1349//#ifdef HAVE_TM_GMTOFF
1350 tmp->tm_gmtoff = offset;
1351#endif
1352 return tmp;
1353 }
1354
1355 static void gmtload(struct state * const sp) {
1356 if (tzload(gmt, sp, TRUE) != 0)
1357 (void) tzparse(gmt, sp, TRUE);
1358 }
1359
1360 /*
1361 ** gmtsub is to gmtime as localsub is to localtime.
1362 */
1363
1364 static struct tm * gmtsub(const time_t *const timep, const int_fast32_t offset, struct tm *const tmp) {
1365 struct tm * result;
1366
1367 if (!gmt_is_set) {
1368 gmt_is_set = TRUE;
1369 gmtload(gmtptr);
1370 }
1371 result = timesub(timep, offset, gmtptr, tmp);
1372 return result;
1373 }
1374
1375 // [[Rcpp::register]]
1376 struct tm * gmtime_(const time_t * const timep) {
1377 return gmtsub(timep, 0L, &tm);
1378 }
1379}
#define SECSPERDAY
Definition date.cpp:297
#define TM_YEAR_BASE
Definition date.cpp:321
#define SECSPERHOUR
Definition date.cpp:296
#define DAYSPERNYEAR
Definition date.cpp:294
#define MAXVAL(t, b)
Definition date.cpp:153
#define is_digit(c)
Definition date.cpp:147
#define SECSPERREPEAT
Definition date.cpp:145
#define SECSPERMIN
Definition date.cpp:290
#define TYPE_INTEGRAL(type)
Definition date.cpp:140
#define MINVAL(t, b)
Definition date.cpp:156
#define EPOCH_WDAY
Definition date.cpp:324
#define MONSPERYEAR
Definition date.cpp:298
#define DAY_OF_YEAR
Definition date.cpp:416
#define days_in_year(year)
#define TZDEFRULESTRING
Definition date.cpp:367
#define TZ_MAX_CHARS
Definition date.cpp:282
#define BIGGEST(a, b)
Definition date.cpp:370
#define HOURSPERDAY
Definition date.cpp:292
#define JULIAN_DAY
Definition date.cpp:415
#define isleap(y)
Definition date.cpp:326
#define DAYSPERWEEK
Definition date.cpp:293
#define EPOCH_YEAR
Definition date.cpp:323
#define TZ_MAX_TYPES
Definition date.cpp:269
#define MY_TZNAME_MAX
Definition date.cpp:376
#define TZDEFRULES
Definition date.cpp:195
#define MINSPERHOUR
Definition date.cpp:291
#define INITIALIZE(x)
Definition date.cpp:148
#define YEARSPERREPEAT
Definition date.cpp:143
#define OPEN_MODE
Definition date.cpp:354
#define TZ_MAX_TIMES
Definition date.cpp:264
#define MONTH_NTH_DAY_OF_WEEK
Definition date.cpp:417
#define gmtptr
Definition date.cpp:433
#define DAYSPERLYEAR
Definition date.cpp:295
#define TZ_MAX_LEAPS
Definition date.cpp:287
#define TZDEFAULT
Definition date.cpp:191
#define SECSPERREPEAT_BITS
Definition date.cpp:146
#define TYPE_BIT(type)
Definition date.cpp:138
#define TYPE_SIGNED(type)
Definition date.cpp:139
Rcpp API.
Definition algo.h:28
static const char * getnum(const char *strp, int *const nump, const int min, const int max)
Definition date.cpp:567
static int_fast64_t detzcode64(const char *const codep)
Definition date.cpp:488
static const char * getrule(const char *strp, struct rule *const rulep)
Definition date.cpp:586
static const char * getsecs(const char *strp, int_fast32_t *secsp)
Definition date.cpp:536
sugar::Min< RTYPE, NA, T > min(const VectorBase< RTYPE, NA, T > &x)
Definition min.h:82
static int differ_by_repeat(const time_t t1, const time_t t0)
Definition date.cpp:495
static int tzparse(const char *name, struct state *sp, int lastditch)
Definition date.cpp:965
static int increment_overflow(int *const ip, int j)
Definition date.cpp:452
static const char gmt[]
Definition date.cpp:357
static void gmtload(struct state *const sp)
Definition date.cpp:1355
static int typesequiv(const struct state *sp, int a, int b)
Definition date.cpp:1201
static struct tm tm
Definition date.cpp:435
static time_t const time_t_max
Definition date.cpp:161
static const char * getqzname(const char *strp, const int delim)
Definition date.cpp:512
static const int mon_lengths[2][MONSPERYEAR]
Definition date.cpp:419
static const char * getzname(const char *strp)
Definition date.cpp:503
static struct tm * gmtsub(const time_t *const timep, const int_fast32_t offset, struct tm *const tmp)
Definition date.cpp:1364
static int gmt_is_set
Definition date.cpp:428
attribute_hidden struct tm * gmtime_(const time_t *const x)
Definition routines.h:136
static const char * getoffset(const char *strp, int_fast32_t *const offsetp)
Definition date.cpp:520
sugar::Max< RTYPE, NA, T > max(const VectorBase< RTYPE, NA, T > &x)
Definition max.h:82
static int leaps_thru_end_of(const int y)
Definition date.cpp:1221
attribute_hidden double mktime00(struct tm &tm)
Definition routines.h:130
static time_t const time_t_min
Definition date.cpp:160
static struct tm * timesub(const time_t *timep, int_fast32_t offset, const struct state *sp, struct tm *tmp)
Definition date.cpp:1226
static int increment_overflow_time(time_t *tp, int_fast32_t j)
Definition date.cpp:467
T as(SEXP x)
Definition as.h:151
static int_fast32_t detzcode(const char *const codep)
Definition date.cpp:481
static struct state gmtmem
Definition date.cpp:431
static int_fast32_t transtime(int year, const struct rule *rulep, int_fast32_t offset)
Definition date.cpp:878
static const int year_lengths[2]
Definition date.cpp:424
static int tzload(const char *name, struct state *const sp, const int doextend)
Definition date.cpp:631
int_fast64_t ls_corr
Definition date.cpp:389
time_t ls_trans
Definition date.cpp:388
int_fast32_t r_time
Definition date.cpp:412
int r_type
Definition date.cpp:408
int r_week
Definition date.cpp:410
int r_day
Definition date.cpp:409
int r_mon
Definition date.cpp:411
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition date.cpp:404
time_t ats[TZ_MAX_TIMES]
Definition date.cpp:399
int timecnt
Definition date.cpp:394
int goback
Definition date.cpp:397
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition date.cpp:403
unsigned char types[TZ_MAX_TIMES]
Definition date.cpp:400
int leapcnt
Definition date.cpp:393
int typecnt
Definition date.cpp:395
int goahead
Definition date.cpp:398
struct ttinfo ttis[TZ_MAX_TYPES]
Definition date.cpp:401
int charcnt
Definition date.cpp:396
int tt_ttisstd
Definition date.cpp:383
int tt_isdst
Definition date.cpp:381
int tt_abbrind
Definition date.cpp:382
int tt_ttisgmt
Definition date.cpp:384
int_fast32_t tt_gmtoff
Definition date.cpp:380
char tzh_ttisgmtcnt[4]
Definition date.cpp:208
char tzh_charcnt[4]
Definition date.cpp:213
char tzh_magic[4]
Definition date.cpp:205
char tzh_leapcnt[4]
Definition date.cpp:210
char tzh_reserved[15]
Definition date.cpp:207
char tzh_timecnt[4]
Definition date.cpp:211
char tzh_ttisstdcnt[4]
Definition date.cpp:209
char tzh_typecnt[4]
Definition date.cpp:212
char tzh_version[1]
Definition date.cpp:206