13 #include <sys/types.h>
35 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
36 #define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
37 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
38 #define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
53 if ((
long)x < (
long)y)
55 if ((
long)x > (
long)y)
62 #define ne(x,y) (!eq((x),(y)))
63 #define lt(x,y) (cmp((x),(y)) < 0)
64 #define gt(x,y) (cmp((x),(y)) > 0)
65 #define le(x,y) (cmp((x),(y)) <= 0)
66 #define ge(x,y) (cmp((x),(y)) >= 0)
92 #if !(HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG)
96 unsigned long a, b, c;
98 if (x == 0 || y == 0) {
104 a = (
unsigned long)-x;
108 a = (
unsigned long)x;
112 b = (
unsigned long)-y;
115 b = (
unsigned long)y;
117 if (a <= ULONG_MAX / b) {
120 if (c <= (
unsigned long)
LONG_MAX + 1) {
140 #if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
156 #define div(x,y) (rb_funcall((x), id_div, 1, (y)))
167 #define neg(x) (sub(INT2FIX(0), (x)))
168 #define lshift(x,y) (rb_funcall((x), id_lshift, 1, (y)))
192 #define mulquo(x,y,z) (((y) == (z)) ? (x) : quo(mul((x),(y)),(z)))
209 # define INT64toNUM(x) LONG2NUM(x)
210 # define UINT64toNUM(x) ULONG2NUM(x)
211 #elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
212 # define INT64toNUM(x) LL2NUM(x)
213 # define UINT64toNUM(x) ULL2NUM(x)
216 #if defined(HAVE_UINT64_T) && SIZEOF_LONG*2 <= SIZEOF_UINT64_T
221 # define WIDEVALUE_IS_WIDER 1
222 # define UWIDEINT_MAX UINT64_MAX
223 # define WIDEINT_MAX INT64_MAX
224 # define WIDEINT_MIN INT64_MIN
225 # define FIXWINT_P(tv) ((tv) & 1)
226 # define FIXWVtoINT64(tv) RSHIFT((SIGNED_WIDEVALUE)(tv), 1)
227 # define INT64toFIXWV(wi) ((WIDEVALUE)((SIGNED_WIDEVALUE)(wi) << 1 | FIXNUM_FLAG))
228 # define FIXWV_MAX (((int64_t)1 << 62) - 1)
229 # define FIXWV_MIN (-((int64_t)1 << 62))
230 # define FIXWVABLE(wi) (POSFIXWVABLE(wi) && NEGFIXWVABLE(wi))
231 # define WINT2FIXWV(i) WIDEVAL_WRAP(INT64toFIXWV(i))
232 # define FIXWV2WINT(w) FIXWVtoINT64(WIDEVAL_GET(w))
238 # define WIDEVALUE_IS_WIDER 0
239 # define UWIDEINT_MAX ULONG_MAX
240 # define WIDEINT_MAX LONG_MAX
241 # define WIDEINT_MIN LONG_MIN
242 # define FIXWINT_P(v) FIXNUM_P(v)
243 # define FIXWV_MAX FIXNUM_MAX
244 # define FIXWV_MIN FIXNUM_MIN
245 # define FIXWVABLE(i) FIXABLE(i)
246 # define WINT2FIXWV(i) WIDEVAL_WRAP(LONG2FIX(i))
247 # define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
250 #define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
251 #define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
252 #define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
255 #ifdef STRUCT_WIDEVAL
261 # define WIDEVAL_GET(w) ((w).value)
264 # define WIDEVAL_WRAP(v) (v)
265 # define WIDEVAL_GET(w) (w)
268 #if WIDEVALUE_IS_WIDER
277 # define WINT2WV(wi) wint2wv(wi)
279 # define WINT2WV(wi) WIDEVAL_WRAP(LONG2NUM(wi))
285 #if WIDEVALUE_IS_WIDER
294 #if WIDEVALUE_IS_WIDER
296 bdigit_find_maxbit(
BDIGIT d)
299 if (d & ~(
BDIGIT)0xffff) {
323 rb_big_abs_find_maxbit(
VALUE big)
329 while (0 < len && ds[len-1] == 0)
340 rb_big_abs_find_minbit(
VALUE big)
347 for (i = 0; i <
len; i++)
367 maxbit = rb_big_abs_find_maxbit(v);
390 #if WIDEVALUE_IS_WIDER
396 return v2w_bignum(v);
405 #if WIDEVALUE_IS_WIDER
419 #if WIDEVALUE_IS_WIDER
436 #define wne(x,y) (!weq((x),(y)))
437 #define wlt(x,y) (wcmp((x),(y)) < 0)
438 #define wgt(x,y) (wcmp((x),(y)) > 0)
439 #define wle(x,y) (wcmp((x),(y)) <= 0)
440 #define wge(x,y) (wcmp((x),(y)) >= 0)
446 #if WIDEVALUE_IS_WIDER
462 #if WIDEVALUE_IS_WIDER
479 if (x == 0 || y == 0) {
520 #if WIDEVALUE_IS_WIDER
540 #if WIDEVALUE_IS_WIDER
562 #define wmulquo(x,y,z) ((WIDEVAL_GET(y) == WIDEVAL_GET(z)) ? (x) : wquo(wmul((x),(y)),(z)))
563 #define wmulquoll(x,y,z) (((y) == (z)) ? (x) : wquo(wmul((x),WINT2WV(y)),WINT2WV(z)))
569 #if WIDEVALUE_IS_WIDER
714 #ifndef TYPEOF_TIMEVAL_TV_SEC
715 # define TYPEOF_TIMEVAL_TV_SEC time_t
717 #ifndef TYPEOF_TIMEVAL_TV_USEC
718 # if INT_MAX >= 1000000
719 # define TYPEOF_TIMEVAL_TV_USEC int
721 # define TYPEOF_TIMEVAL_TV_USEC long
725 #if SIZEOF_TIME_T == SIZEOF_LONG
727 #elif SIZEOF_TIME_T == SIZEOF_INT
729 #elif SIZEOF_TIME_T == SIZEOF_LONG_LONG
732 # error cannot find integer type which size is same as time_t.
735 #define TIMET_MAX (~(time_t)0 <= 0 ? (time_t)((~(unsigned_time_t)0) >> 1) : (time_t)(~(unsigned_time_t)0))
736 #define TIMET_MIN (~(time_t)0 <= 0 ? (time_t)(((unsigned_time_t)1) << (sizeof(time_t) * CHAR_BIT - 1)) : (time_t)0)
752 #if WIDEVALUE_IS_WIDER
770 #if WIDEVALUE_IS_WIDER
799 #if WIDEVALUE_IS_WIDER
813 return v2w(TIMET2NUM(t));
815 #define TIMET2WV(t) timet2wv(t)
820 #if WIDEVALUE_IS_WIDER
836 return NUM2TIMET(
w2v(w));
838 #define WV2TIMET(t) wv2timet(t)
854 static int tmcmp(
struct tm *a,
struct tm *b);
861 #define leap_year_v_p(y) leap_year_p(NUM2LONG(mod((y), INT2FIX(400))))
864 #define rb_gmtime_r(t, tm) gmtime_r((t), (tm))
865 #define rb_localtime_r(t, tm) localtime_r((t), (tm))
867 static inline struct tm *
870 struct tm *t = gmtime(tp);
875 static inline struct tm *
878 struct tm *t = localtime(tp);
887 #if defined __APPLE__ && defined __LP64__
891 #if defined(HAVE_MKTIME) && defined(LOCALTIME_OVERFLOW_PROBLEM)
897 # if defined(HAVE_STRUCT_TM_TM_GMTOFF)
898 gmtoff1 = result->tm_gmtoff;
901 # if defined(HAVE_STRUCT_TM_TM_GMTOFF)
902 gmtoff2 = tmp.tm_gmtoff;
904 if (*t + gmtoff1 != t2 + gmtoff2)
910 #define LOCALTIME(tm, result) (tzset(),rb_localtime_r2((tm), &(result)))
912 #if !defined(HAVE_STRUCT_TM_TM_GMTOFF)
917 #if defined(HAVE_TIMEGM) && defined(LOCALTIME_OVERFLOW_PROBLEM)
927 # define GMTIME(tm, result) rb_gmtime_r2((tm), &(result))
935 -1 + 31 + 28 + 31 + 30,
936 -1 + 31 + 28 + 31 + 30 + 31,
937 -1 + 31 + 28 + 31 + 30 + 31 + 30,
938 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31,
939 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
940 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
941 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
942 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
950 -1 + 31 + 29 + 31 + 30,
951 -1 + 31 + 29 + 31 + 30 + 31,
952 -1 + 31 + 29 + 31 + 30 + 31 + 30,
953 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31,
954 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
955 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
956 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
957 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
962 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
965 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
971 int tm_year_mod400 = (int)
MOD(tm_year, 400);
972 int tm_yday = tm_mday;
975 tm_yday += leap_year_yday_offset[tm_mon];
977 tm_yday += common_year_yday_offset[tm_mon];
1011 +
DIV(year_mod400 - 69, 4)
1012 -
DIV(year_mod400 - 1, 100)
1013 + (year_mod400 + 299) / 400;
1035 return (
const char *)
v;
1049 const int *yday_offset;
1063 vtm->
wday = (wday + 4) % 7;
1066 vtm->
sec = n % 60; n = n / 60;
1067 vtm->
min = n % 60; n = n / 60;
1084 if (30*365+7+31+29-1 <= n) {
1098 x = n / (365*100 + 24);
1099 n = n % (365*100 + 24);
1101 if (30*365+7+31+29-1 <= n) {
1111 x = n / (365*4 + 1);
1112 n = n % (365*4 + 1);
1114 if (365*2+31+29-1 <= n) {
1115 if (n < 365*2+366) {
1137 for (i = 0; i < 12; i++) {
1138 if (yday_offset[i] < n) {
1140 vtm->
mday = n - yday_offset[
i];
1153 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
1157 int gmtoff_sec, gmtoff_min, gmtoff_hour, gmtoff_day;
1164 if (t->tm_gmtoff < 0) {
1166 gmtoff = -t->tm_gmtoff;
1170 gmtoff = t->tm_gmtoff;
1172 gmtoff_sec = (int)(gmtoff % 60);
1173 gmtoff = gmtoff / 60;
1174 gmtoff_min = (int)(gmtoff % 60);
1175 gmtoff = gmtoff / 60;
1176 gmtoff_hour = (int)gmtoff;
1180 gmtoff_hour *= sign;
1187 result->tm_sec += gmtoff_sec;
1188 if (result->tm_sec < 0) {
1189 result->tm_sec += 60;
1192 if (60 <= result->tm_sec) {
1193 result->tm_sec -= 60;
1198 result->tm_min += gmtoff_min;
1199 if (result->tm_min < 0) {
1200 result->tm_min += 60;
1203 if (60 <= result->tm_min) {
1204 result->tm_min -= 60;
1209 result->tm_hour += gmtoff_hour;
1210 if (result->tm_hour < 0) {
1211 result->tm_hour += 24;
1214 if (24 <= result->tm_hour) {
1215 result->tm_hour -= 24;
1221 if (gmtoff_day < 0) {
1222 if (result->tm_yday == 0) {
1223 result->tm_mday = 31;
1224 result->tm_mon = 11;
1226 result->tm_yday =
leap_year_p(result->tm_year + 1900) ? 365 : 364;
1228 else if (result->tm_mday == 1) {
1229 const int *days_in_month =
leap_year_p(result->tm_year + 1900) ?
1230 leap_year_days_in_month :
1233 result->tm_mday = days_in_month[result->tm_mon];
1240 result->tm_wday = (result->tm_wday + 6) % 7;
1244 if (result->tm_yday == (leap ? 365 : 364)) {
1247 result->tm_mday = 1;
1248 result->tm_yday = 0;
1250 else if (result->tm_mday == (leap ? leap_year_days_in_month :
1251 common_year_days_in_month)[result->tm_mon]) {
1253 result->tm_mday = 1;
1260 result->tm_wday = (result->tm_wday + 1) % 7;
1263 result->tm_isdst = 0;
1264 result->tm_gmtoff = 0;
1265 #if defined(HAVE_TM_ZONE)
1266 result->tm_zone = (
char *)
"UTC";
1270 return GMTIME(timep, *result);
1286 if (this_year == 0) {
1295 this_year = tm->tm_year;
1300 known_leap_seconds_limit = now + (
time_t)(366*86400);
1306 vtm.
mon = result.tm_mon + 1;
1307 vtm.
mday = result.tm_mday;
1308 vtm.
hour = result.tm_hour;
1309 vtm.
min = result.tm_min;
1310 vtm.
sec = result.tm_sec;
1342 tm.tm_mon = vtm->
mon - 1;
1343 tm.tm_mday = vtm->
mday;
1344 tm.tm_hour = vtm->
hour;
1345 tm.tm_min = vtm->
min;
1346 tm.tm_sec = vtm->
sec;
1383 result->
mon = tm.tm_mon + 1;
1384 result->
mday = tm.tm_mday;
1385 result->
hour = tm.tm_hour;
1386 result->
min = tm.tm_min;
1387 result->
sec = tm.tm_sec;
1390 result->
wday = tm.tm_wday;
1391 result->
yday = tm.tm_yday+1;
1392 result->
isdst = tm.tm_isdst;
1393 result->
zone =
"UTC";
1435 { 2034, 2035, 2036, 2031, 2032, 2027, 2033 },
1436 { 2026, 2027, 2033, 2034, 2035, 2030, 2031 },
1437 { 2026, 2032, 2033, 2034, 2035, 2030, 2036 },
1438 { 2035, 2030, 2036, 2026, 2032, 2033, 2034 },
1439 { 2033, 2034, 2035, 2030, 2036, 2026, 2032 },
1440 { 2036, 2026, 2032, 2033, 2034, 2035, 2030 },
1441 { 2035, 2030, 2036, 2026, 2032, 2033, 2034 },
1442 { 2032, 2033, 2034, 2035, 2030, 2036, 2026 },
1443 { 2030, 2036, 2026, 2032, 2033, 2034, 2035 },
1444 { 2034, 2035, 2030, 2036, 2026, 2032, 2033 },
1445 { 2026, 2032, 2033, 2034, 2035, 2030, 2036 },
1446 { 2030, 2036, 2026, 2032, 2033, 2034, 2035 },
1476 2032, 2016, 2028, 2012, 2024, 2036, 2020,
1485 a = (14 - month) / 12;
1486 y = year + 4800 - a;
1487 m = month + 12 * a - 3;
1488 wday = day + (153*m+2)/5 + 365*y + y/4 - y/100 + y/400 + 2;
1511 # if defined(NEGATIVE_TIME_T)
1512 # if SIZEOF_TIME_T <= 4
1514 # define THE_TIME_OLD_ENOUGH ((time_t)0x80000000)
1518 # define THE_TIME_OLD_ENOUGH ((time_t)(1600-1970)*366*24*60*60)
1522 isdst = tm.tm_isdst;
1529 isdst = tm.tm_isdst;
1547 vtm2.
year =
INT2FIX(compat_leap_month_table[wday]);
1549 vtm2.
year =
INT2FIX(compat_common_month_table[vtm_utc->
mon-1][wday]);
1552 t = NUM2TIMET(timev);
1556 *isdst_ret = tm.tm_isdst;
1565 static long now_gmtoff = 0;
1566 static const char *now_zone =
"UTC";
1572 *isdst_ret = tm.tm_isdst;
1574 *zone_ret = now_zone;
1584 off = vtm1->
sec - vtm2->
sec;
1585 off += (vtm1->
min - vtm2->
min) * 60;
1586 off += (vtm1->
hour - vtm2->
hour) * 3600;
1588 off +=
lt(vtm1->
year, vtm2->
year) ? -24*3600 : 24*3600;
1589 else if (vtm1->
mon != vtm2->
mon)
1590 off += vtm1->
mon < vtm2->
mon ? -24*3600 : 24*3600;
1592 off += vtm1->
mday < vtm2->
mday ? -24*3600 : 24*3600;
1604 struct vtm vtm1, vtm2;
1609 if (l < INT_MIN || INT_MAX < l)
1611 tm.tm_year = (int)l;
1620 tm.tm_mon = vtm->
mon-1;
1621 tm.tm_mday = vtm->
mday;
1622 tm.tm_hour = vtm->
hour;
1623 tm.tm_min = vtm->
min;
1624 tm.tm_sec = vtm->
sec;
1625 tm.tm_isdst = vtm->
isdst;
1660 if (
weq(timew1, timew2))
1685 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
1686 *gmtoff = tm.tm_gmtoff;
1695 if (l->tm_year != u->tm_year)
1696 off = l->tm_year < u->tm_year ? -1 : 1;
1697 else if (l->tm_mon != u->tm_mon)
1698 off = l->tm_mon < u->tm_mon ? -1 : 1;
1699 else if (l->tm_mday != u->tm_mday)
1700 off = l->tm_mday < u->tm_mday ? -1 : 1;
1703 off = off * 24 + l->tm_hour - u->tm_hour;
1704 off = off * 60 + l->tm_min - u->tm_min;
1705 off = off * 60 + l->tm_sec - u->tm_sec;
1710 #if defined(HAVE_TM_ZONE)
1712 #elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT)
1714 *zone =
zone_str(tzname[daylight && tm.tm_isdst]);
1718 strftime(buf,
sizeof(buf),
"%Z", &tm);
1734 #if WIDEVALUE_IS_WIDER && SIZEOF_TIME_T < SIZEOF_INT64_T
1743 timexv =
w2v(timew);
1769 result->
mon = tm.tm_mon + 1;
1770 result->
mday = tm.tm_mday;
1771 result->
hour = tm.tm_hour;
1772 result->
min = tm.tm_min;
1773 result->
sec = tm.tm_sec;
1775 result->
wday = tm.tm_wday;
1776 result->
yday = tm.tm_yday+1;
1777 result->
isdst = tm.tm_isdst;
1779 result->
zone = zone;
1793 result->
isdst = isdst;
1794 result->
zone = zone;
1806 #define GetTimeval(obj, tobj) \
1807 TypedData_Get_Struct((obj), struct time_object, &time_data_type, (tobj))
1809 #define IsTimeval(obj) rb_typeddata_is_kind_of((obj), &time_data_type)
1811 #define TIME_UTC_P(tobj) ((tobj)->gmt == 1)
1812 #define TIME_SET_UTC(tobj) ((tobj)->gmt = 1)
1814 #define TIME_LOCALTIME_P(tobj) ((tobj)->gmt == 0)
1815 #define TIME_SET_LOCALTIME(tobj) ((tobj)->gmt = 0)
1817 #define TIME_FIXOFF_P(tobj) ((tobj)->gmt == 2)
1818 #define TIME_SET_FIXOFF(tobj, off) \
1820 (tobj)->vtm.utc_offset = (off), \
1821 (tobj)->vtm.zone = NULL)
1823 #define TIME_COPY_GMT(tobj1, tobj2) \
1824 ((tobj1)->gmt = (tobj2)->gmt, \
1825 (tobj1)->vtm.utc_offset = (tobj2)->vtm.utc_offset, \
1826 (tobj1)->vtm.zone = (tobj2)->vtm.zone)
1829 #define MAKE_TM(time, tobj) \
1831 if ((tobj)->tm_got == 0) { \
1832 time_get_tm((time), (tobj)); \
1851 if (tobj)
xfree(tobj);
1947 #ifdef HAVE_CLOCK_GETTIME
1948 if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
2007 subsec =
neg(subsec);
2036 if (60 <= vtm->
sec) {
2047 if (60 <= vtm->
min) {
2054 if (vtm->
hour < 0) {
2058 if (24 <= vtm->
hour) {
2066 if (vtm->
mon == 1 && vtm->
mday == 1) {
2072 else if (vtm->
mday == 1) {
2074 leap_year_days_in_month :
2077 vtm->
mday = days_in_month[vtm->
mon-1];
2088 if (vtm->
mon == 12 && vtm->
mday == 31) {
2094 else if (vtm->
mday == (leap ? leap_year_days_in_month :
2095 common_year_days_in_month)[vtm->
mon-1]) {
2118 (s[0] !=
'+' && s[0] !=
'-') ||
2125 n = (s[1] * 10 + s[2] -
'0' * 11) * 3600;
2126 n += (s[4] * 10 + s[5] -
'0' * 11) * 60;
2148 rb_scan_args(argc, argv,
"16", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6]);
2261 if (nsec >= 1000000000) {
2262 tmp = sec + nsec / 1000000000;
2264 if (sec > 0 && tmp < 0) {
2270 tmp = sec +
NDIV(nsec,1000000000);
2271 nsec =
NMOD(nsec,1000000000);
2272 if (sec < 0 && tmp > 0) {
2277 #ifndef NEGATIVE_TIME_T
2312 if (usec >= 1000000) {
2313 long sec2 = usec / 1000000;
2317 usec -= sec2 * 1000000;
2320 else if (usec <= 1000000) {
2321 long sec2 = usec / 1000000;
2325 usec -= sec2 * 1000000;
2358 const char *tstr = interval ?
"time interval" :
"time";
2361 #ifndef NEGATIVE_TIME_T
2365 switch (
TYPE(num)) {
2367 t.
tv_sec = NUM2TIMET(num);
2368 if (interval && t.
tv_sec < 0)
2383 else if ((t.
tv_nsec = (
int)(-d*1e9+0.5)) > 0) {
2395 t.
tv_sec = NUM2TIMET(num);
2396 if (interval && t.
tv_sec < 0)
2408 if (interval && t.
tv_sec < 0)
2536 "jan",
"feb",
"mar",
"apr",
"may",
"jun",
2537 "jul",
"aug",
"sep",
"oct",
"nov",
"dec",
2597 for (i=0; i<12; i++) {
2607 if (
'0' <= c && c <=
'9') {
2628 if ( vtm->
mon < 1 || vtm->
mon > 12
2631 || (vtm->
hour == 24 && (vtm->
min > 0 || vtm->
sec > 0))
2632 || vtm->
min < 0 || vtm->
min > 59
2633 || vtm->
sec < 0 || vtm->
sec > 60
2668 rb_scan_args(argc, argv,
"17", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6],&v[7]);
2695 if (!
NIL_P(v[6]) && argc == 7) {
2710 return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
2716 long tm_year = tm->tm_year;
2717 int tm_yday = tm->tm_mday;
2719 tm_yday += leap_year_yday_offset[tm->tm_mon];
2721 tm_yday += common_year_yday_offset[tm->tm_mon];
2729 return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 +
2733 DIV(tm_year-1,100) +
2734 DIV(tm_year+299,400))*86400;
2738 #define DEBUG_FIND_TIME_NUMGUESS
2739 #define DEBUG_GUESSRANGE
2742 #ifdef DEBUG_GUESSRANGE
2743 #define DEBUG_REPORT_GUESSRANGE fprintf(stderr, "find time guess range: %ld - %ld : %lu\n", guess_lo, guess_hi, (unsigned_time_t)(guess_hi-guess_lo))
2745 #define DEBUG_REPORT_GUESSRANGE
2748 #ifdef DEBUG_FIND_TIME_NUMGUESS
2749 #define DEBUG_FIND_TIME_NUMGUESS_INC find_time_numguess++,
2750 static unsigned long long find_time_numguess;
2752 static VALUE find_time_numguess_getter(
void)
2754 return ULL2NUM(find_time_numguess);
2757 #define DEBUG_FIND_TIME_NUMGUESS_INC
2763 time_t guess, guess0, guess_lo, guess_hi;
2764 struct tm *tm, tm0, tm_lo, tm_hi;
2771 #define GUESS(p) (DEBUG_FIND_TIME_NUMGUESS_INC (utc_p ? gmtime_with_leapsecond((p), &result) : LOCALTIME((p), result)))
2776 find_dst = 0 < tptr->tm_isdst;
2778 #if defined(HAVE_MKTIME)
2780 if (!utc_p && (guess = mktime(&tm0)) != -1) {
2782 if (tm &&
tmcmp(tptr, tm) == 0) {
2789 if (tm0.tm_mon < 0) {
2796 else if (11 < tm0.tm_mon) {
2803 else if (tm0.tm_mday < 1) {
2810 leap_year_days_in_month :
2811 common_year_days_in_month)[tm0.tm_mon]) < tm0.tm_mday) {
2817 else if (tm0.tm_hour < 0) {
2822 else if (23 < tm0.tm_hour) {
2827 else if (tm0.tm_min < 0) {
2831 else if (59 < tm0.tm_min) {
2835 else if (tm0.tm_sec < 0) {
2838 else if (60 < tm0.tm_sec) {
2846 d =
tmcmp(tptr, tm);
2847 if (d == 0) {
goto found; }
2850 guess -= 24 * 60 * 60;
2854 guess += 24 * 60 * 60;
2857 if (guess_lo < guess && guess < guess_hi && (tm =
GUESS(&guess)) !=
NULL) {
2858 d =
tmcmp(tptr, tm);
2859 if (d == 0) {
goto found; }
2868 tm =
GUESS(&guess_lo);
2869 if (!tm)
goto error;
2870 d =
tmcmp(tptr, tm);
2871 if (d < 0)
goto out_of_range;
2872 if (d == 0) { guess = guess_lo;
goto found; }
2875 tm =
GUESS(&guess_hi);
2876 if (!tm)
goto error;
2877 d =
tmcmp(tptr, tm);
2878 if (d > 0)
goto out_of_range;
2879 if (d == 0) { guess = guess_hi;
goto found; }
2886 while (guess_lo + 1 < guess_hi) {
2889 guess = guess_lo / 2 + guess_hi / 2;
2890 if (guess <= guess_lo)
2891 guess = guess_lo + 1;
2892 else if (guess >= guess_hi)
2893 guess = guess_hi - 1;
2899 guess = guess_hi - (guess0_hi - guess0);
2900 if (guess == guess_hi)
2904 else if (status == 2) {
2906 guess = guess_lo + (guess0 - guess0_lo);
2907 if (guess == guess_lo)
2911 if (guess <= guess_lo || guess_hi <= guess) {
2913 #ifdef DEBUG_GUESSRANGE
2914 if (guess <= guess_lo) fprintf(stderr,
"too small guess: %ld <= %ld\n", guess, guess_lo);
2915 if (guess_hi <= guess) fprintf(stderr,
"too big guess: %ld <= %ld\n", guess_hi, guess);
2922 if (!tm)
goto error;
2924 d =
tmcmp(tptr, tm);
2942 guess2 = guess - 2 * 60 * 60;
2945 if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
2946 tptr->tm_min != tm->tm_min ||
2947 tptr->tm_sec != tm->tm_sec) {
2948 guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
2949 (tm->tm_min - tptr->tm_min) * 60 +
2950 (tm->tm_sec - tptr->tm_sec);
2951 if (tptr->tm_mday != tm->tm_mday)
2952 guess2 += 24 * 60 * 60;
2953 if (guess != guess2) {
2955 if (tm &&
tmcmp(tptr, tm) == 0) {
2967 guess2 = guess + 2 * 60 * 60;
2970 if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
2971 tptr->tm_min != tm->tm_min ||
2972 tptr->tm_sec != tm->tm_sec) {
2973 guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
2974 (tm->tm_min - tptr->tm_min) * 60 +
2975 (tm->tm_sec - tptr->tm_sec);
2976 if (tptr->tm_mday != tm->tm_mday)
2977 guess2 -= 24 * 60 * 60;
2978 if (guess != guess2) {
2980 if (tm &&
tmcmp(tptr, tm) == 0) {
3005 tptr_tm_yday =
calc_tm_yday(tptr->tm_year, tptr->tm_mon, tptr->tm_mday);
3008 ((tptr->tm_year - tm_lo.tm_year) * 365 +
3009 ((tptr->tm_year-69)/4) -
3010 ((tptr->tm_year-1)/100) +
3011 ((tptr->tm_year+299)/400) -
3012 ((tm_lo.tm_year-69)/4) +
3013 ((tm_lo.tm_year-1)/100) -
3014 ((tm_lo.tm_year+299)/400) +
3016 tm_lo.tm_yday) * 86400 +
3017 (tptr->tm_hour - tm_lo.tm_hour) * 3600 +
3018 (tptr->tm_min - tm_lo.tm_min) * 60 +
3019 (tptr->tm_sec - (tm_lo.tm_sec == 60 ? 59 : tm_lo.tm_sec));
3024 return "time out of range";
3027 return "gmtime/localtime error";
3035 else if (a->
mon != b->
mon)
3036 return a->
mon < b->
mon ? -1 : 1;
3041 else if (a->
min != b->
min)
3042 return a->
min < b->
min ? -1 : 1;
3043 else if (a->
sec != b->
sec)
3044 return a->
sec < b->
sec ? -1 : 1;
3054 if (a->tm_year != b->tm_year)
3055 return a->tm_year < b->tm_year ? -1 : 1;
3056 else if (a->tm_mon != b->tm_mon)
3057 return a->tm_mon < b->tm_mon ? -1 : 1;
3058 else if (a->tm_mday != b->tm_mday)
3059 return a->tm_mday < b->tm_mday ? -1 : 1;
3060 else if (a->tm_hour != b->tm_hour)
3061 return a->tm_hour < b->tm_hour ? -1 : 1;
3062 else if (a->tm_min != b->tm_min)
3063 return a->tm_min < b->tm_min ? -1 : 1;
3064 else if (a->tm_sec != b->tm_sec)
3065 return a->tm_sec < b->tm_sec ? -1 : 1;
3346 if (n == 0)
return INT2FIX(0);
3424 if (copy == time)
return copy;
3660 return strftimev(
"%a %b %e %T %Y", time);
3686 return strftimev(
"%Y-%m-%d %H:%M:%S UTC", time);
3688 return strftimev(
"%Y-%m-%d %H:%M:%S %z", time);
3782 rb_warn(
"Time#succ is obsolete; use time + 1");
3790 #define time_succ rb_time_succ
3832 VALUE ndigits,
v, a, b, den;
4021 #define wday_p(n) {\
4022 struct time_object *tobj;\
4023 GetTimeval(time, tobj);\
4024 MAKE_TM(time, tobj);\
4025 return (tobj->vtm.wday == (n)) ? Qtrue : Qfalse;\
4291 rb_strftime(
char *s,
size_t maxsize,
const char *format,
4295 #define SMALLBUF 100
4317 if (len != 0 || (**buf ==
'\0' &&
errno != ERANGE))
return len;
4318 for (size=1024; ; size*=2) {
4324 len =
rb_strftime(*buf, size, format, vtm, timev, gmt);
4334 if (size >= 1024 * flen) {
4354 if (buf != buffer)
xfree(buf);
4549 rb_warning(
"strftime called with empty format string");
4551 else if (memchr(fmt,
'\0', len)) {
4553 const char *
p = fmt, *pe = fmt +
len;
4560 if (buf != buffer) {
4564 for (fmt = p; p < pe && !*
p; ++
p);
4574 if (buf != buffer)
xfree(buf);
4603 if (year < 1900 || 1900+0xffff < year)
4630 for (i=0; i<4; i++) {
4631 buf[
i] = (
unsigned char)p;
4634 for (i=4; i<8; i++) {
4635 buf[
i] = (
unsigned char)s;
4660 int len = (int)
sizeof(buf);
4661 buf[1] = (char)((nsec % 10) << 4);
4663 buf[0] = (char)(nsec % 10);
4665 buf[0] |= (char)((nsec % 10) << 4);
4713 VALUE submicro, nano_num, nano_den, offset;
4719 #define get_attr(attr, iffound) \
4720 attr = rb_attr_get(str, id_##attr); \
4721 if (!NIL_P(attr)) { \
4724 st_delete(rb_generic_ivar_table(str), &data, 0); \
4742 for (i=0; i<4; i++) {
4745 for (i=4; i<8; i++) {
4746 s |= buf[
i]<<(8*(i-4));
4749 if ((p & (1UL<<31)) == 0) {
4759 gmt = (int)((p >> 30) & 0x1);
4761 vtm.
year =
INT2FIX(((
int)(p >> 14) & 0xffff) + 1900);
4762 vtm.
mon = ((int)(p >> 10) & 0xf) + 1;
4763 vtm.
mday = (int)(p >> 5) & 0x1f;
4764 vtm.
hour = (int) p & 0x1f;
4765 vtm.
min = (int)(s >> 26) & 0x3f;
4766 vtm.
sec = (int)(s >> 20) & 0x3f;
4772 usec = (
long)(s & 0xfffff);
4777 if (nano_num !=
Qnil) {
4781 else if (submicro !=
Qnil) {
4789 if (10 <= (digit = ptr[0] >> 4))
goto end_submicro;
4790 nsec += digit * 100;
4791 if (10 <= (digit = ptr[0] & 0xf))
goto end_submicro;
4795 if (10 <= (digit = ptr[1] >> 4))
goto end_submicro;
4806 tobj->
timew = timew;
4810 else if (!
NIL_P(offset)) {
4855 #define rb_intern(str) rb_intern_const(str)
4955 #ifdef DEBUG_FIND_TIME_NUMGUESS