41 static struct tm *
gmtime_(
const time_t *
const timep);
53 m_d = Rcpp::as<double>(d);
67 Date::Date(
const std::string &s,
const std::string &fmt) {
70 m_d = Rcpp::as<int>(asDate(strptime(s, fmt,
"UTC")));
74 Date::Date(
const unsigned int &mon,
const unsigned int &day,
const unsigned int &year) {
79 if (mon >=
baseYear && day <= 12 && year <= 31) {
81 m_tm.tm_mon = day - 1;
85 m_tm.tm_mon = mon - 1;
99 if (
this != &newdate) {
108 time_t t = 24*60*60 *
m_d;
120 static const int days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
122 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
123 #define days_in_year(year) (isleap(year) ? 366 : 365)
129 day = tm.tm_mday - 1;
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;
140 for(i = 0; i < tm.tm_mon; i++) day += days_in_month[i];
141 if (tm.tm_mon > 1 &&
isleap(year0)) day++;
145 for (year = 1970; year < year0; year++)
147 }
else if (year0 < 1970) {
148 for (year = 1969; year >= year0; year--)
153 if ((tm.tm_wday = (day + 4) % 7) < 0) tm.tm_wday += 7;
155 return tm.tm_sec + (tm.tm_min * 60) + (tm.tm_hour * 3600)
156 + (day + excess * 730485) * 86400.0;
163 newdate.
m_d += offset;
164 time_t t = 24*60*60 * newdate.
m_d;
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"));
185 return datetimeclass ;
189 SEXP
x =
PROTECT( Rf_ScalarReal( d ) ) ;
196 SEXP
x =
PROTECT(Rf_ScalarReal( d ) ) ;
197 Rf_setAttrib(x, R_ClassSymbol, Rf_mkString(
"Date"));
216 m_dt = Rcpp::as<double>(d);
228 m_dt = Rcpp::as<double>(asPOSIXct(strptime(s, fmt)));
239 if (
this != &newdt) {
248 if (R_FINITE(
m_dt)) {
249 time_t t =
static_cast<time_t
>(floor(
m_dt));
252 m_us =
static_cast<int>(::Rf_fround( (
m_dt - t) * 1.0e6, 0.0));
263 newdt.
m_dt += offset;
264 time_t t =
static_cast<time_t
>(floor(newdt.
m_dt));
265 newdt.
m_tm = *gmtime(&t);
266 newdt.
m_us =
static_cast<int>(::Rf_fround( (newdt.
m_dt - t) * 1.0e6, 0.0));
278 template<> SEXP wrap_extra_steps<Rcpp::Datetime>( SEXP
x ){
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);
295 throw std::range_error(
"DatetimeVector: null vector in constructor");
297 for (i = 0; i < len; i++)
298 v[i] =
Datetime( static_cast<double>(REAL(vec)[i]));
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());
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());
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());
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());
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);
356 throw std::range_error(
"DateVector: null vector in constructor");
358 for (i = 0; i < len; i++)
359 v[i] =
Date( static_cast<double>(REAL(vec)[i]));
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());
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());
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());
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());
410 #include "sys/types.h"
420 # define EOVERFLOW 79
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
438 #define AVGSECSPERYEAR 31556952L
439 #define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
440 #define SECSPERREPEAT_BITS 34
441 #define is_digit(c) ((unsigned)(c) - '0' <= 9)
442 #define INITIALIZE(x) (x = 0)
468 #define TZDIR "/usr/local/etc/zoneinfo"
472 #define TZDEFAULT "localtime"
476 #define TZDEFRULES "America/New_York"
483 #define TZ_MAGIC "TZif"
538 #define TZ_MAX_TIMES 1200
543 #define TZ_MAX_TYPES 256
550 #define TZ_MAX_TYPES 20
555 #define TZ_MAX_CHARS 50
560 #define TZ_MAX_LEAPS 50
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
576 #define TM_WEDNESDAY 3
577 #define TM_THURSDAY 4
579 #define TM_SATURDAY 6
582 #define TM_FEBRUARY 1
589 #define TM_SEPTEMBER 8
591 #define TM_NOVEMBER 10
592 #define TM_DECEMBER 11
594 #define TM_YEAR_BASE baseYear // was: 1900, baseYear defined above
596 #define EPOCH_YEAR 1970
597 #define EPOCH_WDAY TM_THURSDAY
599 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
613 #define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
620 #define OPEN_MODE (O_RDONLY | O_BINARY)
623 #define OPEN_MODE O_RDONLY
626 static const char gmt[] =
"GMT";
635 #ifndef TZDEFRULESTRING
636 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
639 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
642 #define MY_TZNAME_MAX TZNAME_MAX
645 #define MY_TZNAME_MAX 255
685 #define DAY_OF_YEAR 1
686 #define MONTH_NTH_DAY_OF_WEEK 2
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 }
702 #define gmtptr (&gmtmem)
708 static int tzparse(
const char * name,
struct state * sp,
int lastditch);
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);
722 return (*number < number0) != (delta < 0);
729 result = (codep[0] & 0x80) ? ~0L : 0;
730 for (i = 0; i < 4; ++
i)
731 result = (result << 8) | (codep[
i] & 0xff);
739 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
740 for (i = 0; i < 8; ++
i)
741 result = result * 256 + (codep[i] & 0xff);
756 while ((c = *strp) !=
'\0' && !
is_digit(c) && c !=
',' && c !=
'-' &&
762 static const char *
getqzname(
const char *strp,
const int delim) {
765 while ((c = *strp) !=
'\0' && c != delim)
770 static const char *
getoffset(
const char * strp,
long *
const offsetp) {
776 }
else if (*strp ==
'+')
782 *offsetp = -*offsetp;
786 static const char *
getsecs(
const char * strp,
long *
const secsp) {
808 strp =
getnum(strp, &num, 0, SECSPERMIN);
817 static const char *
getnum(
const char * strp,
int *
const nump,
const int min,
const int max) {
821 if (strp == NULL || !
is_digit(c = *strp))
825 num = num * 10 + (c -
'0');
836 static const char *
getrule(
const char * strp,
struct rule *
const rulep) {
844 }
else if (*strp ==
'M') {
880 static int tzload(
const char * name,
struct state *
const sp,
const int doextend) {
888 char buf[2 *
sizeof(
struct tzhead) +
910 char fullname[FILENAME_MAX + 1];
915 doaccess = name[0] ==
'/';
920 snprintf(buf, 1000,
"%s/share/zoneinfo",
926 if ((strlen(p) + strlen(name) + 1) >=
sizeof fullname)
928 (void) strcpy(fullname, p);
929 (void) strcat(fullname,
"/");
930 (void) strcat(fullname, name);
934 if (strchr(name,
'.') != NULL) doaccess = TRUE;
944 if ((fid = open(name,
OPEN_MODE)) == -1) {
952 nread = read(fid, u.buf,
sizeof u.buf);
953 if (close(fid) < 0 || nread <= 0)
955 for (stored = 4; stored <= 8; stored *= 2) {
959 ttisstdcnt = (int)
detzcode(u.tzhead.tzh_ttisstdcnt);
960 ttisgmtcnt = (int)
detzcode(u.tzhead.tzh_ttisgmtcnt);
965 p = u.tzhead.tzh_charcnt +
sizeof u.tzhead.tzh_charcnt;
970 (ttisstdcnt != sp->
typecnt && ttisstdcnt != 0) ||
971 (ttisgmtcnt != sp->
typecnt && ttisgmtcnt != 0))
973 if (nread - (p - u.buf) <
987 sp->
types[
i] = (
unsigned char) *p++;
994 ttisp = &sp->
ttis[
i];
997 ttisp->
tt_isdst = (
unsigned char) *p++;
1006 sp->
chars[i] = *p++;
1007 sp->
chars[i] =
'\0';
1011 lsisp = &sp->
lsis[
i];
1017 for (i = 0; i < sp->
typecnt; ++
i) {
1020 ttisp = &sp->
ttis[
i];
1021 if (ttisstdcnt == 0)
1029 for (i = 0; i < sp->
typecnt; ++
i) {
1032 ttisp = &sp->
ttis[
i];
1033 if (ttisgmtcnt == 0)
1046 for (i = 0; i < sp->
timecnt - 2; ++
i)
1047 if (sp->
ats[i] > sp->
ats[i + 1]) {
1060 for (j = 0; j + i < sp->
timecnt; ++
j) {
1071 if (u.tzhead.tzh_version[0] ==
'\0')
1074 for (i = 0; i < nread; ++
i)
1079 if (stored >= (
int)
sizeof(time_t) &&
TYPE_INTEGRAL(time_t))
1082 if (doextend && nread > 2 &&
1083 u.buf[0] ==
'\n' && u.buf[nread - 1] ==
'\n' &&
1088 u.buf[nread - 1] =
'\0';
1089 result =
tzparse(&u.buf[1], &ts, FALSE);
1090 if (result == 0 && ts.
typecnt == 2 &&
1092 for (i = 0; i < 2; ++
i)
1123 static time_t
transtime(
const time_t janfirst,
const int year,
const struct rule *
const rulep,
const long offset) {
1127 int d, m1, yy0, yy1, yy2, dow;
1142 if (leapyear && rulep->
r_day >= 60)
1160 for (i = 0; i < rulep->
r_mon - 1; ++
i)
1167 m1 = (rulep->
r_mon + 9) % 12 + 1;
1168 yy0 = (rulep->
r_mon <= 2) ? (year - 1) : year;
1171 dow = ((26 * m1 - 2) / 10 +
1172 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1181 d = rulep->
r_day - dow;
1184 for (i = 1; i < rulep->
r_week; ++
i) {
1204 return value + rulep->
r_time + offset;
1207 static int tzparse(
const char * name,
struct state *
const sp,
const int lastditch) {
1208 const char * stdname;
1209 const char * dstname;
1215 unsigned char * typep;
1222 stdlen = strlen(name);
1224 if (stdlen >=
sizeof sp->
chars)
1225 stdlen = (
sizeof sp->
chars) - 1;
1234 stdlen = name - stdname;
1238 stdlen = name - stdname;
1247 if (load_result != 0)
1249 if (*name !=
'\0') {
1255 dstlen = name - dstname;
1260 dstlen = name - dstname;
1262 if (*name !=
'\0' && *name !=
',' && *name !=
';') {
1267 if (*name ==
'\0' && load_result != 0)
1269 if (*name ==
',' || *name ==
';') {
1278 if ((name =
getrule(name, &start)) == NULL)
1282 if ((name =
getrule(name, &end)) == NULL)
1305 starttime =
transtime(janfirst, year, &start,
1307 endtime =
transtime(janfirst, year, &end,
1309 if (starttime > endtime) {
1321 newfirst = janfirst;
1324 if (newfirst <= janfirst)
1326 janfirst = newfirst;
1329 long theirstdoffset;
1330 long theirdstoffset;
1342 for (i = 0; i < sp->
timecnt; ++
i) {
1351 for (i = 0; i < sp->
timecnt; ++
i) {
1363 theiroffset = theirstdoffset;
1368 for (i = 0; i < sp->
timecnt; ++
i) {
1389 sp->
ats[
i] += dstoffset -
1392 sp->
ats[
i] += stdoffset -
1398 theirdstoffset = theiroffset;
1399 else theirstdoffset = theiroffset;
1427 (void) strncpy(cp, stdname, stdlen);
1431 (void) strncpy(cp, dstname, dstlen);
1432 *(cp + dstlen) =
'\0';
1458 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
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;
1480 hit = ((i == 0 && lp->
ls_corr > 0) ||
1507 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1510 idelta = (tdays < 0) ? -1 : 1;
1523 seconds = tdays * SECSPERDAY + 0.5;
1531 rem += offset - corr;
1536 while (rem >= SECSPERDAY) {
1553 tmp->tm_yday = idays;
1564 if (tmp->tm_wday < 0)
1573 tmp->tm_sec = (int) (rem %
SECSPERMIN) + hit;
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);
1580 tmp->TM_GMTOFF = offset;
1590 static struct tm *
gmtsub(
const time_t *
const timep,
const long offset,
struct tm *
const tmp) {