13 #include <sys/types.h>
30 #if defined(HAVE_SYS_TIME_H)
39 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
40 #define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
41 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
42 #define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
57 if ((
long)x < (
long)y)
59 if ((
long)x > (
long)y)
66 #define ne(x,y) (!eq((x),(y)))
67 #define lt(x,y) (cmp((x),(y)) < 0)
68 #define gt(x,y) (cmp((x),(y)) > 0)
69 #define le(x,y) (cmp((x),(y)) <= 0)
70 #define ge(x,y) (cmp((x),(y)) >= 0)
96 #if !(HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG)
100 unsigned long a,
b,
c;
102 if (x == 0 || y == 0) {
108 a = (
unsigned long)-x;
112 a = (
unsigned long)x;
116 b = (
unsigned long)-y;
119 b = (
unsigned long)y;
121 if (a <= ULONG_MAX / b) {
124 if (c <= (
unsigned long)
LONG_MAX + 1) {
144 #if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
160 #define div(x,y) (rb_funcall((x), id_div, 1, (y)))
171 #define neg(x) (sub(INT2FIX(0), (x)))
172 #define lshift(x,y) (rb_funcall((x), id_lshift, 1, (y)))
196 #define mulquo(x,y,z) (((y) == (z)) ? (x) : quo(mul((x),(y)),(z)))
213 # define INT64toNUM(x) LONG2NUM(x)
214 # define UINT64toNUM(x) ULONG2NUM(x)
215 #elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
216 # define INT64toNUM(x) LL2NUM(x)
217 # define UINT64toNUM(x) ULL2NUM(x)
220 #if defined(HAVE_UINT64_T) && SIZEOF_LONG*2 <= SIZEOF_UINT64_T
225 # define WIDEVALUE_IS_WIDER 1
226 # define UWIDEINT_MAX UINT64_MAX
227 # define WIDEINT_MAX INT64_MAX
228 # define WIDEINT_MIN INT64_MIN
229 # define FIXWINT_P(tv) ((tv) & 1)
230 # define FIXWVtoINT64(tv) RSHIFT((SIGNED_WIDEVALUE)(tv), 1)
231 # define INT64toFIXWV(wi) ((WIDEVALUE)((SIGNED_WIDEVALUE)(wi) << 1 | FIXNUM_FLAG))
232 # define FIXWV_MAX (((int64_t)1 << 62) - 1)
233 # define FIXWV_MIN (-((int64_t)1 << 62))
234 # define FIXWVABLE(wi) (POSFIXWVABLE(wi) && NEGFIXWVABLE(wi))
235 # define WINT2FIXWV(i) WIDEVAL_WRAP(INT64toFIXWV(i))
236 # define FIXWV2WINT(w) FIXWVtoINT64(WIDEVAL_GET(w))
242 # define WIDEVALUE_IS_WIDER 0
243 # define UWIDEINT_MAX ULONG_MAX
244 # define WIDEINT_MAX LONG_MAX
245 # define WIDEINT_MIN LONG_MIN
246 # define FIXWINT_P(v) FIXNUM_P(v)
247 # define FIXWV_MAX FIXNUM_MAX
248 # define FIXWV_MIN FIXNUM_MIN
249 # define FIXWVABLE(i) FIXABLE(i)
250 # define WINT2FIXWV(i) WIDEVAL_WRAP(LONG2FIX(i))
251 # define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
254 #define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
255 #define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
256 #define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
259 #ifdef STRUCT_WIDEVAL
265 # define WIDEVAL_GET(w) ((w).value)
268 # define WIDEVAL_WRAP(v) (v)
269 # define WIDEVAL_GET(w) (w)
272 #if WIDEVALUE_IS_WIDER
281 # define WINT2WV(wi) wint2wv(wi)
283 # define WINT2WV(wi) WIDEVAL_WRAP(LONG2NUM(wi))
289 #if WIDEVALUE_IS_WIDER
298 #if WIDEVALUE_IS_WIDER
308 else if (sign == -1) {
312 else if (sign == +1) {
328 #if WIDEVALUE_IS_WIDER
334 return v2w_bignum(v);
343 #if WIDEVALUE_IS_WIDER
357 #if WIDEVALUE_IS_WIDER
374 #define wne(x,y) (!weq((x),(y)))
375 #define wlt(x,y) (wcmp((x),(y)) < 0)
376 #define wgt(x,y) (wcmp((x),(y)) > 0)
377 #define wle(x,y) (wcmp((x),(y)) <= 0)
378 #define wge(x,y) (wcmp((x),(y)) >= 0)
384 #if WIDEVALUE_IS_WIDER
400 #if WIDEVALUE_IS_WIDER
417 if (x == 0 || y == 0) {
458 #if WIDEVALUE_IS_WIDER
478 #if WIDEVALUE_IS_WIDER
500 #define wmulquo(x,y,z) ((WIDEVAL_GET(y) == WIDEVAL_GET(z)) ? (x) : wquo(wmul((x),(y)),(z)))
501 #define wmulquoll(x,y,z) (((y) == (z)) ? (x) : wquo(wmul((x),WINT2WV(y)),WINT2WV(z)))
507 #if WIDEVALUE_IS_WIDER
668 #if WIDEVALUE_IS_WIDER
686 #if WIDEVALUE_IS_WIDER
715 #if WIDEVALUE_IS_WIDER
716 if (TIMET_MIN == 0) {
729 return v2w(TIMET2NUM(t));
731 #define TIMET2WV(t) timet2wv(t)
736 #if WIDEVALUE_IS_WIDER
739 if (TIMET_MIN == 0) {
746 if (wi < TIMET_MIN || TIMET_MAX < wi)
752 return NUM2TIMET(
w2v(w));
754 #define WV2TIMET(t) wv2timet(t)
772 static int tmcmp(
struct tm *
a,
struct tm *
b);
774 static const char *
find_time_t(
struct tm *tptr,
int utc_p, time_t *
tp);
779 #define leap_year_v_p(y) leap_year_p(NUM2LONG(mod((y), INT2FIX(400))))
782 #define rb_gmtime_r(t, tm) gmtime_r((t), (tm))
783 #define rb_localtime_r(t, tm) localtime_r((t), (tm))
785 static inline struct tm *
788 struct tm *
t = gmtime(tp);
793 static inline struct tm *
796 struct tm *
t = localtime(tp);
805 #if defined __APPLE__ && defined __LP64__
806 if (*t != (time_t)(
int)*t)
return NULL;
809 #if defined(HAVE_MKTIME) && defined(LOCALTIME_OVERFLOW_PROBLEM)
815 # if defined(HAVE_STRUCT_TM_TM_GMTOFF)
816 gmtoff1 = result->tm_gmtoff;
819 # if defined(HAVE_STRUCT_TM_TM_GMTOFF)
820 gmtoff2 = tmp.tm_gmtoff;
822 if (*t + gmtoff1 != t2 + gmtoff2)
828 #define LOCALTIME(tm, result) (tzset(),rb_localtime_r2((tm), &(result)))
830 #if !defined(HAVE_STRUCT_TM_TM_GMTOFF)
835 #if defined(HAVE_TIMEGM) && defined(LOCALTIME_OVERFLOW_PROBLEM)
838 time_t t2 = timegm(&tmp);
845 # define GMTIME(tm, result) rb_gmtime_r2((tm), &(result))
853 -1 + 31 + 28 + 31 + 30,
854 -1 + 31 + 28 + 31 + 30 + 31,
855 -1 + 31 + 28 + 31 + 30 + 31 + 30,
856 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31,
857 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
858 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
859 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
860 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
868 -1 + 31 + 29 + 31 + 30,
869 -1 + 31 + 29 + 31 + 30 + 31,
870 -1 + 31 + 29 + 31 + 30 + 31 + 30,
871 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31,
872 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
873 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
874 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
875 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
880 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
883 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
889 int tm_year_mod400 = (
int)
MOD(tm_year, 400);
890 int tm_yday = tm_mday;
893 tm_yday += leap_year_yday_offset[tm_mon];
895 tm_yday += common_year_yday_offset[tm_mon];
929 +
DIV(year_mod400 - 69, 4)
930 -
DIV(year_mod400 - 1, 100)
931 + (year_mod400 + 299) / 400;
946 const char *
s = (
const char *)*key;
947 const char **
ret = (
const char **)arg;
950 *ret = (
const char *)*value;
973 const int *yday_offset;
987 vtm->
wday = (wday + 4) % 7;
990 vtm->
sec = n % 60; n = n / 60;
991 vtm->
min = n % 60; n = n / 60;
1008 if (30*365+7+31+29-1 <= n) {
1022 x = n / (365*100 + 24);
1023 n = n % (365*100 + 24);
1025 if (30*365+7+31+29-1 <= n) {
1035 x = n / (365*4 + 1);
1036 n = n % (365*4 + 1);
1038 if (365*2+31+29-1 <= n) {
1039 if (n < 365*2+366) {
1061 for (i = 0; i < 12; i++) {
1062 if (yday_offset[i] < n) {
1064 vtm->
mday = n - yday_offset[
i];
1077 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
1081 int gmtoff_sec, gmtoff_min, gmtoff_hour, gmtoff_day;
1088 if (t->tm_gmtoff < 0) {
1090 gmtoff = -t->tm_gmtoff;
1094 gmtoff = t->tm_gmtoff;
1096 gmtoff_sec = (
int)(gmtoff % 60);
1097 gmtoff = gmtoff / 60;
1098 gmtoff_min = (
int)(gmtoff % 60);
1099 gmtoff = gmtoff / 60;
1100 gmtoff_hour = (
int)gmtoff;
1104 gmtoff_hour *= sign;
1111 result->tm_sec += gmtoff_sec;
1112 if (result->tm_sec < 0) {
1113 result->tm_sec += 60;
1116 if (60 <= result->tm_sec) {
1117 result->tm_sec -= 60;
1122 result->tm_min += gmtoff_min;
1123 if (result->tm_min < 0) {
1124 result->tm_min += 60;
1127 if (60 <= result->tm_min) {
1128 result->tm_min -= 60;
1133 result->tm_hour += gmtoff_hour;
1134 if (result->tm_hour < 0) {
1135 result->tm_hour += 24;
1138 if (24 <= result->tm_hour) {
1139 result->tm_hour -= 24;
1145 if (gmtoff_day < 0) {
1146 if (result->tm_yday == 0) {
1147 result->tm_mday = 31;
1148 result->tm_mon = 11;
1150 result->tm_yday =
leap_year_p(result->tm_year + 1900) ? 365 : 364;
1152 else if (result->tm_mday == 1) {
1153 const int *days_in_month =
leap_year_p(result->tm_year + 1900) ?
1154 leap_year_days_in_month :
1157 result->tm_mday = days_in_month[result->tm_mon];
1164 result->tm_wday = (result->tm_wday + 6) % 7;
1168 if (result->tm_yday == (leap ? 365 : 364)) {
1171 result->tm_mday = 1;
1172 result->tm_yday = 0;
1174 else if (result->tm_mday == (leap ? leap_year_days_in_month :
1175 common_year_days_in_month)[result->tm_mon]) {
1177 result->tm_mday = 1;
1184 result->tm_wday = (result->tm_wday + 1) % 7;
1187 result->tm_isdst = 0;
1188 result->tm_gmtoff = 0;
1189 #if defined(HAVE_TM_ZONE)
1190 result->tm_zone = (
char *)
"UTC";
1194 return GMTIME(timep, *result);
1210 if (this_year == 0) {
1219 this_year = tm->tm_year;
1221 if (TIMET_MAX - now < (time_t)(366*86400))
1222 known_leap_seconds_limit = TIMET_MAX;
1224 known_leap_seconds_limit = now + (time_t)(366*86400);
1230 vtm.
mon = result.tm_mon + 1;
1231 vtm.
mday = result.tm_mday;
1232 vtm.
hour = result.tm_hour;
1233 vtm.
min = result.tm_min;
1234 vtm.
sec = result.tm_sec;
1266 tm.tm_mon = vtm->
mon - 1;
1267 tm.tm_mday = vtm->
mday;
1268 tm.tm_hour = vtm->
hour;
1269 tm.tm_min = vtm->
min;
1270 tm.tm_sec = vtm->
sec;
1307 result->
mon = tm.tm_mon + 1;
1308 result->
mday = tm.tm_mday;
1309 result->
hour = tm.tm_hour;
1310 result->
min = tm.tm_min;
1311 result->
sec = tm.tm_sec;
1314 result->
wday = tm.tm_wday;
1315 result->
yday = tm.tm_yday+1;
1316 result->
isdst = tm.tm_isdst;
1317 result->
zone =
"UTC";
1359 { 2034, 2035, 2036, 2031, 2032, 2027, 2033 },
1360 { 2026, 2027, 2033, 2034, 2035, 2030, 2031 },
1361 { 2026, 2032, 2033, 2034, 2035, 2030, 2036 },
1362 { 2035, 2030, 2036, 2026, 2032, 2033, 2034 },
1363 { 2033, 2034, 2035, 2030, 2036, 2026, 2032 },
1364 { 2036, 2026, 2032, 2033, 2034, 2035, 2030 },
1365 { 2035, 2030, 2036, 2026, 2032, 2033, 2034 },
1366 { 2032, 2033, 2034, 2035, 2030, 2036, 2026 },
1367 { 2030, 2036, 2026, 2032, 2033, 2034, 2035 },
1368 { 2034, 2035, 2030, 2036, 2026, 2032, 2033 },
1369 { 2026, 2032, 2033, 2034, 2035, 2030, 2036 },
1370 { 2030, 2036, 2026, 2032, 2033, 2034, 2035 },
1400 2032, 2016, 2028, 2012, 2024, 2036, 2020,
1409 a = (14 - month) / 12;
1410 y = year + 4800 -
a;
1411 m = month + 12 * a - 3;
1412 wday = day + (153*m+2)/5 + 365*y + y/4 - y/100 + y/400 + 2;
1435 # if defined(NEGATIVE_TIME_T)
1436 # if SIZEOF_TIME_T <= 4
1438 # define THE_TIME_OLD_ENOUGH ((time_t)0x80000000)
1442 # define THE_TIME_OLD_ENOUGH ((time_t)(1600-1970)*366*24*60*60)
1446 isdst = tm.tm_isdst;
1453 isdst = tm.tm_isdst;
1471 vtm2.
year =
INT2FIX(compat_leap_month_table[wday]);
1473 vtm2.
year =
INT2FIX(compat_common_month_table[vtm_utc->
mon-1][wday]);
1476 t = NUM2TIMET(timev);
1480 *isdst_ret = tm.tm_isdst;
1488 static time_t now = 0;
1489 static long now_gmtoff = 0;
1490 static const char *now_zone =
"UTC";
1496 *isdst_ret = tm.tm_isdst;
1498 *zone_ret = now_zone;
1508 off = vtm1->
sec - vtm2->
sec;
1509 off += (vtm1->
min - vtm2->
min) * 60;
1510 off += (vtm1->
hour - vtm2->
hour) * 3600;
1512 off +=
lt(vtm1->
year, vtm2->
year) ? -24*3600 : 24*3600;
1513 else if (vtm1->
mon != vtm2->
mon)
1514 off += vtm1->
mon < vtm2->
mon ? -24*3600 : 24*3600;
1516 off += vtm1->
mday < vtm2->
mday ? -24*3600 : 24*3600;
1528 struct vtm vtm1, vtm2;
1533 if (l < INT_MIN || INT_MAX < l)
1535 tm.tm_year = (
int)l;
1544 tm.tm_mon = vtm->
mon-1;
1545 tm.tm_mday = vtm->
mday;
1546 tm.tm_hour = vtm->
hour;
1547 tm.tm_min = vtm->
min;
1548 tm.tm_sec = vtm->
sec;
1549 tm.tm_isdst = vtm->
isdst;
1584 if (
weq(timew1, timew2))
1609 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
1610 *gmtoff = tm.tm_gmtoff;
1619 if (l->tm_year != u->tm_year)
1620 off = l->tm_year < u->tm_year ? -1 : 1;
1621 else if (l->tm_mon != u->tm_mon)
1622 off = l->tm_mon < u->tm_mon ? -1 : 1;
1623 else if (l->tm_mday != u->tm_mday)
1624 off = l->tm_mday < u->tm_mday ? -1 : 1;
1627 off = off * 24 + l->tm_hour - u->tm_hour;
1628 off = off * 60 + l->tm_min - u->tm_min;
1629 off = off * 60 + l->tm_sec - u->tm_sec;
1634 #if defined(HAVE_TM_ZONE)
1638 *zone =
zone_str(
"(NO-TIMEZONE-ABBREVIATION)");
1639 #elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT)
1641 *zone =
zone_str(tzname[daylight && tm.tm_isdst]);
1645 strftime(buf,
sizeof(buf),
"%Z", &tm);
1661 #if WIDEVALUE_IS_WIDER && SIZEOF_TIME_T < SIZEOF_INT64_T
1670 #if SIZEOF_TIME_T == SIZEOF_INT64_T
1673 if (~(time_t)0 <= 0) {
1683 timexv =
w2v(timew);
1709 result->
mon = tm.tm_mon + 1;
1710 result->
mday = tm.tm_mday;
1711 result->
hour = tm.tm_hour;
1712 result->
min = tm.tm_min;
1713 result->
sec = tm.tm_sec;
1715 result->
wday = tm.tm_wday;
1716 result->
yday = tm.tm_yday+1;
1717 result->
isdst = tm.tm_isdst;
1719 result->
zone = zone;
1733 result->
isdst = isdst;
1734 result->
zone = zone;
1746 #define GetTimeval(obj, tobj) ((tobj) = get_timeval(obj))
1747 #define GetNewTimeval(obj, tobj) ((tobj) = get_new_timeval(obj))
1749 #define IsTimeval(obj) rb_typeddata_is_kind_of((obj), &time_data_type)
1750 #define TIME_INIT_P(tobj) ((tobj)->gmt != -1)
1752 #define TIME_UTC_P(tobj) ((tobj)->gmt == 1)
1753 #define TIME_SET_UTC(tobj) ((tobj)->gmt = 1)
1755 #define TIME_LOCALTIME_P(tobj) ((tobj)->gmt == 0)
1756 #define TIME_SET_LOCALTIME(tobj) ((tobj)->gmt = 0)
1758 #define TIME_FIXOFF_P(tobj) ((tobj)->gmt == 2)
1759 #define TIME_SET_FIXOFF(tobj, off) \
1761 (tobj)->vtm.utc_offset = (off), \
1762 (tobj)->vtm.zone = NULL)
1764 #define TIME_COPY_GMT(tobj1, tobj2) \
1765 ((tobj1)->gmt = (tobj2)->gmt, \
1766 (tobj1)->vtm.utc_offset = (tobj2)->vtm.utc_offset, \
1767 (tobj1)->vtm.zone = (tobj2)->vtm.zone)
1770 #define MAKE_TM(time, tobj) \
1772 if ((tobj)->tm_got == 0) { \
1773 time_get_tm((time), (tobj)); \
1792 if (tobj)
xfree(tobj);
1912 #ifdef HAVE_CLOCK_GETTIME
1972 subsec =
neg(subsec);
2001 if (60 <= vtm->
sec) {
2012 if (60 <= vtm->
min) {
2019 if (vtm->
hour < 0) {
2023 if (24 <= vtm->
hour) {
2031 if (vtm->
mon == 1 && vtm->
mday == 1) {
2037 else if (vtm->
mday == 1) {
2039 leap_year_days_in_month :
2042 vtm->
mday = days_in_month[vtm->
mon-1];
2053 if (vtm->
mon == 12 && vtm->
mday == 31) {
2059 else if (vtm->
mday == (leap ? leap_year_days_in_month :
2060 common_year_days_in_month)[vtm->
mon-1]) {
2087 if (s[6] !=
':')
goto invalid_utc_offset;
2089 n += (s[7] * 10 + s[8] -
'0' * 11);
2091 if (s[0] !=
'+' && s[0] !=
'-')
goto invalid_utc_offset;
2093 if (s[3] !=
':')
goto invalid_utc_offset;
2097 goto invalid_utc_offset;
2099 n += (s[1] * 10 + s[2] -
'0' * 11) * 3600;
2100 n += (s[4] * 10 + s[5] -
'0' * 11) * 60;
2122 rb_scan_args(argc, argv,
"16", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6]);
2231 if (nsec >= 1000000000) {
2232 sec2 = nsec / 1000000000;
2233 if (TIMET_MAX - sec2 < sec) {
2236 nsec -= sec2 * 1000000000;
2239 else if (nsec < 0) {
2240 sec2 =
NDIV(nsec,1000000000);
2241 if (sec < TIMET_MIN - sec2) {
2244 nsec -= sec2 * 1000000000;
2247 #ifndef NEGATIVE_TIME_T
2283 if (usec >= 1000000) {
2284 long sec2 = usec / 1000000;
2285 if (sec > TIMET_MAX - sec2) {
2288 usec -= sec2 * 1000000;
2291 else if (usec < 0) {
2292 long sec2 =
NDIV(usec,1000000);
2293 if (sec < TIMET_MIN - sec2) {
2296 usec -= sec2 * 1000000;
2329 const char *tstr = interval ?
"time interval" :
"time";
2332 #ifndef NEGATIVE_TIME_T
2336 switch (
TYPE(num)) {
2338 t.
tv_sec = NUM2TIMET(num);
2339 if (interval && t.
tv_sec < 0)
2353 if (t.
tv_nsec >= 1000000000) {
2358 else if ((t.
tv_nsec = (
int)(-d*1e9+0.5)) > 0) {
2370 t.
tv_sec = NUM2TIMET(num);
2371 if (interval && t.
tv_sec < 0)
2383 if (interval && t.
tv_sec < 0)
2513 "jan",
"feb",
"mar",
"apr",
"may",
"jun",
2514 "jul",
"aug",
"sep",
"oct",
"nov",
"dec",
2574 for (i=0; i<12; i++) {
2584 if (
'0' <= c && c <=
'9') {
2613 if ( vtm->
mon < 1 || vtm->
mon > 12
2616 || (vtm->
hour == 24 && (vtm->
min > 0 || vtm->
sec > 0))
2617 || vtm->
min < 0 || vtm->
min > 59
2618 || vtm->
sec < 0 || vtm->
sec > 60
2653 rb_scan_args(argc, argv,
"17", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6],&v[7]);
2680 if (!
NIL_P(v[6]) && argc == 7) {
2695 return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
2701 long tm_year = tm->tm_year;
2702 int tm_yday = tm->tm_mday;
2704 tm_yday += leap_year_yday_offset[tm->tm_mon];
2706 tm_yday += common_year_yday_offset[tm->tm_mon];
2714 return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 +
2718 DIV(tm_year-1,100) +
2719 DIV(tm_year+299,400))*86400;
2723 #define DEBUG_FIND_TIME_NUMGUESS
2724 #define DEBUG_GUESSRANGE
2727 #ifdef DEBUG_GUESSRANGE
2728 #define DEBUG_REPORT_GUESSRANGE fprintf(stderr, "find time guess range: %ld - %ld : %"PRI_TIMET_PREFIX"u\n", guess_lo, guess_hi, (unsigned_time_t)(guess_hi-guess_lo))
2730 #define DEBUG_REPORT_GUESSRANGE
2733 #ifdef DEBUG_FIND_TIME_NUMGUESS
2734 #define DEBUG_FIND_TIME_NUMGUESS_INC find_time_numguess++,
2735 static unsigned long long find_time_numguess;
2737 static VALUE find_time_numguess_getter(
void)
2739 return ULL2NUM(find_time_numguess);
2742 #define DEBUG_FIND_TIME_NUMGUESS_INC
2748 time_t guess, guess0, guess_lo, guess_hi;
2749 struct tm *tm, tm0, tm_lo, tm_hi;
2756 #define GUESS(p) (DEBUG_FIND_TIME_NUMGUESS_INC (utc_p ? gmtime_with_leapsecond((p), &result) : LOCALTIME((p), result)))
2758 guess_lo = TIMET_MIN;
2759 guess_hi = TIMET_MAX;
2761 find_dst = 0 < tptr->tm_isdst;
2763 #if defined(HAVE_MKTIME)
2765 if (!utc_p && (guess = mktime(&tm0)) != -1) {
2767 if (tm &&
tmcmp(tptr, tm) == 0) {
2774 if (tm0.tm_mon < 0) {
2781 else if (11 < tm0.tm_mon) {
2788 else if (tm0.tm_mday < 1) {
2795 leap_year_days_in_month :
2796 common_year_days_in_month)[tm0.tm_mon]) < tm0.tm_mday) {
2802 else if (tm0.tm_hour < 0) {
2807 else if (23 < tm0.tm_hour) {
2812 else if (tm0.tm_min < 0) {
2816 else if (59 < tm0.tm_min) {
2820 else if (tm0.tm_sec < 0) {
2823 else if (60 < tm0.tm_sec) {
2831 d =
tmcmp(tptr, tm);
2832 if (d == 0) {
goto found; }
2835 guess -= 24 * 60 * 60;
2839 guess += 24 * 60 * 60;
2842 if (guess_lo < guess && guess < guess_hi && (tm =
GUESS(&guess)) !=
NULL) {
2843 d =
tmcmp(tptr, tm);
2844 if (d == 0) {
goto found; }
2853 tm =
GUESS(&guess_lo);
2854 if (!tm)
goto error;
2855 d =
tmcmp(tptr, tm);
2856 if (d < 0)
goto out_of_range;
2857 if (d == 0) { guess = guess_lo;
goto found; }
2860 tm =
GUESS(&guess_hi);
2861 if (!tm)
goto error;
2862 d =
tmcmp(tptr, tm);
2863 if (d > 0)
goto out_of_range;
2864 if (d == 0) { guess = guess_hi;
goto found; }
2871 while (guess_lo + 1 < guess_hi) {
2874 guess = guess_lo / 2 + guess_hi / 2;
2875 if (guess <= guess_lo)
2876 guess = guess_lo + 1;
2877 else if (guess >= guess_hi)
2878 guess = guess_hi - 1;
2884 guess = guess_hi - (guess0_hi - guess0);
2885 if (guess == guess_hi)
2889 else if (status == 2) {
2891 guess = guess_lo + (guess0 - guess0_lo);
2892 if (guess == guess_lo)
2896 if (guess <= guess_lo || guess_hi <= guess) {
2898 #ifdef DEBUG_GUESSRANGE
2899 if (guess <= guess_lo) fprintf(stderr,
"too small guess: %ld <= %ld\n", guess, guess_lo);
2900 if (guess_hi <= guess) fprintf(stderr,
"too big guess: %ld <= %ld\n", guess_hi, guess);
2907 if (!tm)
goto error;
2909 d =
tmcmp(tptr, tm);
2927 guess2 = guess - 2 * 60 * 60;
2930 if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
2931 tptr->tm_min != tm->tm_min ||
2932 tptr->tm_sec != tm->tm_sec) {
2933 guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
2934 (tm->tm_min - tptr->tm_min) * 60 +
2935 (tm->tm_sec - tptr->tm_sec);
2936 if (tptr->tm_mday != tm->tm_mday)
2937 guess2 += 24 * 60 * 60;
2938 if (guess != guess2) {
2940 if (tm &&
tmcmp(tptr, tm) == 0) {
2952 guess2 = guess + 2 * 60 * 60;
2955 if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
2956 tptr->tm_min != tm->tm_min ||
2957 tptr->tm_sec != tm->tm_sec) {
2958 guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
2959 (tm->tm_min - tptr->tm_min) * 60 +
2960 (tm->tm_sec - tptr->tm_sec);
2961 if (tptr->tm_mday != tm->tm_mday)
2962 guess2 -= 24 * 60 * 60;
2963 if (guess != guess2) {
2965 if (tm &&
tmcmp(tptr, tm) == 0) {
2990 tptr_tm_yday =
calc_tm_yday(tptr->tm_year, tptr->tm_mon, tptr->tm_mday);
2993 ((tptr->tm_year - tm_lo.tm_year) * 365 +
2994 ((tptr->tm_year-69)/4) -
2995 ((tptr->tm_year-1)/100) +
2996 ((tptr->tm_year+299)/400) -
2997 ((tm_lo.tm_year-69)/4) +
2998 ((tm_lo.tm_year-1)/100) -
2999 ((tm_lo.tm_year+299)/400) +
3001 tm_lo.tm_yday) * 86400 +
3002 (tptr->tm_hour - tm_lo.tm_hour) * 3600 +
3003 (tptr->tm_min - tm_lo.tm_min) * 60 +
3004 (tptr->tm_sec - (tm_lo.tm_sec == 60 ? 59 : tm_lo.tm_sec));
3009 return "time out of range";
3012 return "gmtime/localtime error";
3020 else if (a->
mon != b->
mon)
3021 return a->
mon < b->
mon ? -1 : 1;
3026 else if (a->
min != b->
min)
3027 return a->
min < b->
min ? -1 : 1;
3028 else if (a->
sec != b->
sec)
3029 return a->
sec < b->
sec ? -1 : 1;
3039 if (a->tm_year != b->tm_year)
3040 return a->tm_year < b->tm_year ? -1 : 1;
3041 else if (a->tm_mon != b->tm_mon)
3042 return a->tm_mon < b->tm_mon ? -1 : 1;
3043 else if (a->tm_mday != b->tm_mday)
3044 return a->tm_mday < b->tm_mday ? -1 : 1;
3045 else if (a->tm_hour != b->tm_hour)
3046 return a->tm_hour < b->tm_hour ? -1 : 1;
3047 else if (a->tm_min != b->tm_min)
3048 return a->tm_min < b->tm_min ? -1 : 1;
3049 else if (a->tm_sec != b->tm_sec)
3050 return a->tm_sec < b->tm_sec ? -1 : 1;
3333 if (n == 0)
return INT2FIX(0);
3769 rb_warn(
"Time#succ is obsolete; use time + 1");
3777 #define time_succ rb_time_succ
4009 #define wday_p(n) {\
4010 struct time_object *tobj;\
4011 GetTimeval(time, tobj);\
4012 MAKE_TM(time, tobj);\
4013 return (tobj->vtm.wday == (n)) ? Qtrue : Qfalse;\
4280 #define SMALLBUF 100
4302 if (len != 0 || (**buf ==
'\0' &&
errno != ERANGE))
return len;
4303 for (size=1024; ; size*=2) {
4309 len =
rb_strftime(*buf, size, format, enc, vtm, timev, gmt);
4319 if (size >= 1024 * flen) {
4340 if (buf != buffer)
xfree(buf);
4552 rb_warning(
"strftime called with empty format string");
4554 else if (memchr(fmt,
'\0', len)) {
4556 const char *
p =
fmt, *pe = fmt +
len;
4564 if (buf != buffer) {
4568 for (fmt = p; p < pe && !*
p; ++
p);
4578 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);
4707 VALUE submicro, nano_num, nano_den, offset,
zone;
4713 #define get_attr(attr, iffound) \
4714 attr = rb_attr_get(str, id_##attr); \
4715 if (!NIL_P(attr)) { \
4718 st_delete(rb_generic_ivar_table(str), &data, 0); \
4738 for (i=0; i<4; i++) {
4741 for (i=4; i<8; i++) {
4742 s |= buf[
i]<<(8*(i-4));
4745 if ((p & (1UL<<31)) == 0) {
4755 gmt = (
int)((p >> 30) & 0x1);
4757 vtm.
year =
INT2FIX(((
int)(p >> 14) & 0xffff) + 1900);
4758 vtm.
mon = ((
int)(p >> 10) & 0xf) + 1;
4759 vtm.
mday = (
int)(p >> 5) & 0x1f;
4761 vtm.
min = (
int)(s >> 26) & 0x3f;
4762 vtm.
sec = (
int)(s >> 20) & 0x3f;
4768 usec = (long)(s & 0xfffff);
4773 if (nano_num !=
Qnil) {
4777 else if (submicro !=
Qnil) {
4785 if (10 <= (digit = ptr[0] >> 4))
goto end_submicro;
4786 nsec += digit * 100;
4787 if (10 <= (digit = ptr[0] & 0xf))
goto end_submicro;
4791 if (10 <= (digit = ptr[1] >> 4))
goto end_submicro;
4803 tobj->
timew = timew;
4807 else if (!
NIL_P(offset)) {
4922 #define rb_intern(str) rb_intern_const(str)
5023 #ifdef DEBUG_FIND_TIME_NUMGUESS
static const rb_data_type_t time_data_type
#define RB_TYPE_P(obj, type)
VALUE rb_big_modulo(VALUE x, VALUE y)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
static VALUE quo(VALUE x, VALUE y)
static int vtmcmp(struct vtm *a, struct vtm *b)
static time_t timegm_noleapsecond(struct tm *tm)
static VALUE w2v(wideval_t w)
VALUE rb_time_num_new(VALUE, VALUE)
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
static VALUE time_mon(VALUE time)
static VALUE time_to_r(VALUE time)
VALUE rb_ary_entry(VALUE ary, long offset)
int gettimeofday(struct timeval *, struct timezone *)
static int obj2int(VALUE obj)
static VALUE time_sunday(VALUE time)
static VALUE time_getlocaltime(int argc, VALUE *argv, VALUE time)
size_t strlen(const char *)
static struct timespec * timew2timespec_exact(wideval_t timew, struct timespec *ts)
VALUE rb_class_new_instance(int, VALUE *, VALUE)
const char * rb_obj_classname(VALUE)
static VALUE time_s_now(VALUE klass)
static VALUE time_utc_or_local(int argc, VALUE *argv, int utc_p, VALUE klass)
static int tmcmp(struct tm *a, struct tm *b)
#define rb_check_trusted(obj)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
static VALUE time_utc_p(VALUE time)
static struct time_object * get_new_timeval(VALUE obj)
#define GetTimeval(obj, tobj)
static wideval_t timelocalw(struct vtm *vtm)
static void split_second(wideval_t timew, wideval_t *timew_p, VALUE *subsecx_p)
rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts))
static VALUE obj2vint(VALUE obj)
VALUE rb_time_nano_new(time_t, long)
static VALUE time_minus(VALUE time1, VALUE time2)
static VALUE small_vtm_sub(struct vtm *vtm1, struct vtm *vtm2)
#define rb_check_frozen(obj)
RUBY_EXTERN VALUE rb_cTime
static VALUE time_hash(VALUE time)
static VALUE time_localtime_m(int argc, VALUE *argv, VALUE time)
static VALUE time_s_alloc(VALUE klass)
static VALUE time_get_tm(VALUE, struct time_object *)
static int calc_tm_yday(long tm_year, int tm_mon, int tm_mday)
VALUE rb_big_plus(VALUE x, VALUE y)
static VALUE time_sec(VALUE time)
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
static int leap_year_p(long y)
#define DEBUG_REPORT_GUESSRANGE
static struct tm * localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone)
static VALUE time_gmtime(VALUE)
static VALUE time_monday(VALUE time)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
static const int common_year_days_in_month[]
static VALUE time_init(int argc, VALUE *argv, VALUE time)
void rb_raise(VALUE exc, const char *fmt,...)
static void vtm_add_offset(struct vtm *vtm, VALUE off)
static VALUE time_round(int argc, VALUE *argv, VALUE time)
static VALUE add(VALUE x, VALUE y)
VALUE rb_obj_class(VALUE)
st_table * st_init_strtable(void)
static VALUE time_plus(VALUE time1, VALUE time2)
static wideval_t wsub(wideval_t wx, wideval_t wy)
void rb_include_module(VALUE klass, VALUE module)
static VALUE time_utc_offset(VALUE time)
static VALUE time_usec(VALUE time)
static int long_mul(long x, long y, long *z)
static int compat_leap_month_table[7]
#define TIME_LOCALTIME_P(tobj)
static VALUE time_init_0(VALUE time)
static struct tm * rb_localtime_r2(const time_t *t, struct tm *result)
static size_t time_memsize(const void *tobj)
static wideval_t wadd(wideval_t wx, wideval_t wy)
static VALUE time_mload(VALUE time, VALUE str)
static VALUE time_wednesday(VALUE time)
static VALUE time_min(VALUE time)
static VALUE time_cmp(VALUE time1, VALUE time2)
int rb_cmpint(VALUE val, VALUE a, VALUE b)
static VALUE time_yday(VALUE time)
static size_t rb_strftime_alloc(char **buf, VALUE formatv, const char *format, rb_encoding *enc, struct vtm *vtm, wideval_t timew, int gmt)
VALUE rb_str_new_frozen(VALUE)
static VALUE strftimev(const char *fmt, VALUE time, rb_encoding *enc)
VALUE rb_equal(VALUE, VALUE)
static int number_of_leap_seconds_known
static VALUE time_add(struct time_object *tobj, VALUE offset, int sign)
static VALUE time_new_timew(VALUE klass, wideval_t timew)
void rb_copy_generic_ivar(VALUE, VALUE)
static struct tm * rb_gmtime_r2(const time_t *t, struct tm *result)
static time_t wv2timet(wideval_t w)
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
static VALUE time_wday(VALUE time)
static wideval_t nsec2timew(time_t sec, long nsec)
static const char * find_time_t(struct tm *tptr, int utc_p, time_t *tp)
static VALUE time_asctime(VALUE time)
static VALUE time_s_at(int argc, VALUE *argv, VALUE klass)
static VALUE time_set_utc_offset(VALUE time, VALUE off)
unsigned long long uint64_t
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
#define GetNewTimeval(obj, tobj)
static wideval_t wmod(wideval_t wx, wideval_t wy)
#define TypedData_Get_Struct(obj, type, data_type, sval)
static VALUE time_load(VALUE klass, VALUE str)
#define StringValuePtr(v)
#define STRCASECMP(s1, s2)
#define get_attr(attr, iffound)
#define wmulquoll(x, y, z)
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
#define TIME_SET_UTC(tobj)
static int obj2subsecx(VALUE obj, VALUE *subsecx)
static VALUE mod(VALUE x, VALUE y)
#define LOCALTIME(tm, result)
VALUE rb_locale_str_new_cstr(const char *)
static VALUE time_saturday(VALUE time)
#define TIME_FIXOFF_P(tobj)
#define StringValueCStr(v)
static int wcmp(wideval_t wx, wideval_t wy)
static VALUE time_subsec(VALUE time)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
static struct vtm * localtimew(wideval_t timew, struct vtm *result)
VALUE rb_check_to_integer(VALUE, const char *)
static void time_arg(int argc, VALUE *argv, struct vtm *vtm)
void rb_sys_fail_str(VALUE mesg)
static wideval_t wdiv(wideval_t wx, wideval_t wy)
#define GMTIME(tm, result)
#define OBJ_INIT_COPY(obj, orig)
static const char * zone_str(const char *s)
static int calc_wday(int year, int month, int day)
static wideval_t wmul(wideval_t wx, wideval_t wy)
#define TIME_INIT_P(tobj)
static VALUE time_eql(VALUE time1, VALUE time2)
unsigned char buf[MIME_BUF_SIZE]
static VALUE validate_utc_offset(VALUE utc_offset)
static struct tm * rb_gmtime_r(const time_t *tp, struct tm *result)
void rb_num_zerodiv(void)
static VALUE guess_local_offset(struct vtm *vtm_utc, int *isdst_ret, const char **zone_ret)
VALUE rb_time_succ(VALUE)
static int weq(wideval_t wx, wideval_t wy)
static VALUE time_localtime(VALUE)
static VALUE time_mday(VALUE time)
static void gmtimew_noleapsecond(wideval_t timew, struct vtm *vtm)
static VALUE utc_offset_arg(VALUE arg)
static VALUE time_to_i(VALUE time)
static void divmodv(VALUE n, VALUE d, VALUE *q, VALUE *r)
size_t rb_strftime_timespec(char *s, size_t maxsize, const char *format, rb_encoding *enc, const struct vtm *vtm, struct timespec *ts, int gmt)
VALUE rb_big_minus(VALUE x, VALUE y)
static VALUE time_to_s(VALUE time)
static VALUE time_to_f(VALUE time)
static const int leap_year_yday_offset[]
static VALUE time_getgmtime(VALUE time)
static struct tm * rb_localtime_r(const time_t *tp, struct tm *result)
static void validate_vtm(struct vtm *vtm)
#define RUBY_TYPED_FREE_IMMEDIATELY
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
#define TIME_COPY_GMT(tobj1, tobj2)
static void time_free(void *tobj)
static wideval_t rb_time_magnify(wideval_t w)
static int min(int a, int b)
rb_encoding * rb_usascii_encoding(void)
static VALUE time_fixoff(VALUE)
static VALUE num_exact(VALUE v)
VALUE rb_obj_untaint(VALUE)
VALUE rb_big_mul(VALUE x, VALUE y)
static VALUE time_init_1(int argc, VALUE *argv, VALUE time)
static int wi_mul(wideint_t x, wideint_t y, wideint_t *z)
static st_table * zone_table
static struct timespec time_timespec(VALUE num, int interval)
static VALUE sub(VALUE x, VALUE y)
int clock_gettime(clockid_t, struct timespec *)
static int timew_out_of_timet_range(wideval_t timew)
size_t rb_absint_size(VALUE val, int *nlz_bits_ret)
VALUE rb_time_new(time_t, long)
static VALUE mul(VALUE x, VALUE y)
void rb_sys_fail(const char *mesg)
static struct vtm * gmtimew(wideval_t timew, struct vtm *result)
static long usec2subsecx(VALUE obj)
static VALUE validate_zone_name(VALUE zone_name)
static int month_arg(VALUE arg)
#define TYPEOF_TIMEVAL_TV_USEC
static VALUE time_tuesday(VALUE time)
static wideval_t rb_time_unmagnify(wideval_t w)
static wideval_t v2w(VALUE v)
static VALUE time_to_a(VALUE time)
static VALUE time_thursday(VALUE time)
#define MEMCPY(p1, p2, type, n)
static const int common_year_yday_offset[]
static struct timeval time_timeval(VALUE num, int interval)
static VALUE time_strftime(VALUE time, VALUE format)
#define rb_enc_str_asciicompat_p(str)
static wideval_t timegmw_noleapsecond(struct vtm *vtm)
static VALUE time_hour(VALUE time)
static time_t known_leap_seconds_limit
VALUE rb_str_cat(VALUE, const char *, long)
rb_encoding * rb_enc_get(VALUE obj)
struct timeval rb_time_interval(VALUE num)
#define TIME_SET_LOCALTIME(tobj)
static VALUE time_mdump(VALUE time)
static void time_mark(void *ptr)
VALUE rb_check_array_type(VALUE ary)
#define TIME_SET_FIXOFF(tobj, off)
static VALUE time_isdst(VALUE time)
static VALUE time_dup(VALUE time)
#define TypedData_Make_Struct(klass, type, data_type, sval)
static VALUE time_s_mkutc(int argc, VALUE *argv, VALUE klass)
static wideval_t timespec2timew(struct timespec *ts)
#define MAKE_TM(time, tobj)
RUBY_EXTERN VALUE rb_cObject
static struct tm * gmtime_with_leapsecond(const time_t *timep, struct tm *result)
static void wmuldivmod(wideval_t wx, wideval_t wy, wideval_t wz, wideval_t *wq, wideval_t *wr)
int rb_respond_to(VALUE, ID)
static int compat_common_month_table[12][7]
static void time_overflow_p(time_t *secp, long *nsecp)
SIGNED_VALUE SIGNED_WIDEVALUE
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
static void init_leap_second_info(void)
rb_ivar_set(yielder, id_memo, LONG2NUM(++count))
VALUE rb_str_new(const char *, long)
static VALUE time_friday(VALUE time)
static const int leap_year_days_in_month[]
static void wdivmod(wideval_t wn, wideval_t wd, wideval_t *wq, wideval_t *wr)
static struct timespec timew2timespec(wideval_t timew)
static VALUE time_zone(VALUE time)
void rb_warning(const char *fmt,...)
static wideval_t timet2wv(time_t t)
static void time_modify(VALUE time)
static VALUE time_s_mktime(int argc, VALUE *argv, VALUE klass)
static int zone_str_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
static VALUE time_year(VALUE time)
struct timespec rb_time_timespec(VALUE time)
#define INTEGER_PACK_NATIVE_BYTE_ORDER
static VALUE rb_time_unmagnify_to_float(wideval_t w)
static VALUE time_init_copy(VALUE copy, VALUE time)
static VALUE time_nsec(VALUE time)
VALUE rb_invcmp(VALUE x, VALUE y)
VALUE rb_check_string_type(VALUE)
static const char months[][4]
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
static struct time_object * get_timeval(VALUE obj)
static int eq(VALUE x, VALUE y)
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
void rb_warn(const char *fmt,...)
static VALUE time_dump(int argc, VALUE *argv, VALUE time)
#define TYPEOF_TIMEVAL_TV_SEC
struct timeval rb_time_timeval(VALUE)
static wideval_t timegmw(struct vtm *vtm)
size_t rb_strftime(char *s, size_t maxsize, const char *format, rb_encoding *enc, const struct vtm *vtm, VALUE timev, int gmt)
static wideval_t wquo(wideval_t wx, wideval_t wy)