12#define _DEFAULT_SOURCE
30#if defined(HAVE_SYS_TIME_H)
42#include "internal/variable.h"
46static ID id_submicro, id_nano_num, id_nano_den, id_offset, id_zone;
47static ID id_nanosecond, id_microsecond, id_millisecond, id_nsec, id_usec;
48static ID id_local_to_utc, id_utc_to_local, id_find_timezone;
49static ID id_year, id_mon, id_mday, id_hour,
id_min, id_sec, id_isdst;
50static VALUE str_utc, str_empty;
54#define id_divmod idDivmod
56#define UTC_ZONE Qundef
62#define NDIV(x,y) (-(-((x)+1)/(y))-1)
63#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
64#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
65#define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
66#define VTM_WDAY_INITVAL (7)
67#define VTM_ISDST_INITVAL (3)
82 if ((
long)x < (
long)y)
84 if ((
long)x > (
long)y)
92#define ne(x,y) (!eq((x),(y)))
93#define lt(x,y) (cmp((x),(y)) < 0)
94#define gt(x,y) (cmp((x),(y)) > 0)
95#define le(x,y) (cmp((x),(y)) <= 0)
96#define ge(x,y) (cmp((x),(y)) >= 0)
122 return rb_fix_mul_fix(x, y);
133 return rb_fix_div_fix(x, y);
145 if (
FIXNUM_P(x))
return rb_fix_mod_fix(x, y);
151#define neg(x) (subv(INT2FIX(0), (x)))
173 VALUE ret = quor(x, y);
181#define mulquov(x,y,z) (((y) == (z)) ? (x) : quov(mulv((x),(y)),(z)))
190 rb_fix_divmod_fix(n, d, q, r);
205# define INT64toNUM(x) LONG2NUM(x)
206#elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
207# define INT64toNUM(x) LL2NUM(x)
210#if defined(HAVE_UINT64_T) && SIZEOF_LONG*2 <= SIZEOF_UINT64_T
215# define WIDEVALUE_IS_WIDER 1
216# define UWIDEINT_MAX UINT64_MAX
217# define WIDEINT_MAX INT64_MAX
218# define WIDEINT_MIN INT64_MIN
219# define FIXWINT_P(tv) ((tv) & 1)
220# define FIXWVtoINT64(tv) RSHIFT((SIGNED_WIDEVALUE)(tv), 1)
221# define INT64toFIXWV(wi) ((WIDEVALUE)((SIGNED_WIDEVALUE)(wi) << 1 | FIXNUM_FLAG))
222# define FIXWV_MAX (((int64_t)1 << 62) - 1)
223# define FIXWV_MIN (-((int64_t)1 << 62))
224# define FIXWVABLE(wi) (POSFIXWVABLE(wi) && NEGFIXWVABLE(wi))
225# define WINT2FIXWV(i) WIDEVAL_WRAP(INT64toFIXWV(i))
226# define FIXWV2WINT(w) FIXWVtoINT64(WIDEVAL_GET(w))
232# define WIDEVALUE_IS_WIDER 0
233# define UWIDEINT_MAX ULONG_MAX
234# define WIDEINT_MAX LONG_MAX
235# define WIDEINT_MIN LONG_MIN
236# define FIXWINT_P(v) FIXNUM_P(v)
237# define FIXWV_MAX FIXNUM_MAX
238# define FIXWV_MIN FIXNUM_MIN
239# define FIXWVABLE(i) FIXABLE(i)
240# define WINT2FIXWV(i) WIDEVAL_WRAP(LONG2FIX(i))
241# define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
244#define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
245#define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
246#define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
247#define MUL_OVERFLOW_FIXWV_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXWV_MIN, FIXWV_MAX)
256# define WIDEVAL_GET(w) ((w).value)
259# define WIDEVAL_WRAP(v) (v)
260# define WIDEVAL_GET(w) (w)
263#if WIDEVALUE_IS_WIDER
272# define WINT2WV(wi) wint2wv(wi)
274# define WINT2WV(wi) WIDEVAL_WRAP(LONG2NUM(wi))
280#if WIDEVALUE_IS_WIDER
289#if WIDEVALUE_IS_WIDER
299 else if (sign == -1) {
303 else if (sign == +1) {
319#if WIDEVALUE_IS_WIDER
325 return v2w_bignum(v);
334#if WIDEVALUE_IS_WIDER
348#if WIDEVALUE_IS_WIDER
365#define wne(x,y) (!weq((x),(y)))
366#define wlt(x,y) (wcmp((x),(y)) < 0)
367#define wgt(x,y) (wcmp((x),(y)) > 0)
368#define wle(x,y) (wcmp((x),(y)) <= 0)
369#define wge(x,y) (wcmp((x),(y)) >= 0)
374#if WIDEVALUE_IS_WIDER
380 return v2w(addv(w2v(wx), w2v(wy)));
386#if WIDEVALUE_IS_WIDER
392 return v2w(subv(w2v(wx), w2v(wy)));
398#if WIDEVALUE_IS_WIDER
404 return v2w(mulv(w2v(wx), w2v(wy)));
410#if WIDEVALUE_IS_WIDER
422 return v2w(quov(w2v(wx), w2v(wy)));
425#define wmulquo(x,y,z) ((WIDEVAL_GET(y) == WIDEVAL_GET(z)) ? (x) : wquo(wmul((x),(y)),(z)))
426#define wmulquoll(x,y,z) (((y) == (z)) ? (x) : wquo(wmul((x),WINT2WV(y)),WINT2WV(z)))
428#if WIDEVALUE_IS_WIDER
455 if (d > 0 ? r < 0 : r > 0) {
471#if WIDEVALUE_IS_WIDER
472 if (wdivmod0(wn, wd, wq, wr))
return;
474 divmodv(w2v(wn), w2v(wd), &vq, &vr);
487 wdivmod(wmul(wx,wy), wz, wq, wr);
493#if WIDEVALUE_IS_WIDER
495 if (wdivmod0(wx, wy, &q, &dmy))
return q;
497 return v2w(divv(w2v(wx), w2v(wy)));
503#if WIDEVALUE_IS_WIDER
505 if (wdivmod0(wx, wy, &dmy, &r))
return r;
507 return v2w(modv(w2v(wx), w2v(wy)));
557rb_time_unmagnify_to_rational(
wideval_t w)
565 return v2w(rb_time_unmagnify_to_rational(w));
572#if WIDEVALUE_IS_WIDER
604#if WIDEVALUE_IS_WIDER
605 if (TIMET_MIN == 0) {
618 return v2w(TIMET2NUM(
t));
620#define TIMET2WV(t) timet2wv(t)
625#if WIDEVALUE_IS_WIDER
628 if (TIMET_MIN == 0) {
635 if (wi < TIMET_MIN || TIMET_MAX < wi)
641 return NUM2TIMET(w2v(w));
643#define WV2TIMET(t) wv2timet(t)
646static VALUE rb_cTimeTM;
648static int obj2int(
VALUE obj);
652static VALUE validate_utc_offset(
VALUE utc_offset);
653static VALUE validate_zone_name(
VALUE zone_name);
654static void validate_vtm(
struct vtm *vtm);
662static time_t timegm_noleapsecond(
struct tm *tm);
663static int tmcmp(
struct tm *a,
struct tm *b);
664static int vtmcmp(
struct vtm *a,
struct vtm *b);
665static const char *find_time_t(
struct tm *tptr,
int utc_p, time_t *tp);
667static struct vtm *localtimew(
wideval_t timew,
struct vtm *result);
669static int leap_year_p(
long y);
670#define leap_year_v_p(y) leap_year_p(NUM2LONG(modv((y), INT2FIX(400))))
693rb_localtime_r(
const time_t *
t,
struct tm *result)
695#if defined __APPLE__ && defined __LP64__
696 if (*
t != (time_t)(
int)*
t)
return NULL;
703 struct tm *tmp = localtime(
t);
704 if (tmp) *result = *tmp;
707#if defined(HAVE_MKTIME) && defined(LOCALTIME_OVERFLOW_PROBLEM)
711 struct tm tmp = *result;
714# if defined(HAVE_STRUCT_TM_TM_GMTOFF)
715 gmtoff1 = result->tm_gmtoff;
716 gmtoff2 = tmp.tm_gmtoff;
718 if (*
t + gmtoff1 != t2 + gmtoff2)
724#define LOCALTIME(tm, result) rb_localtime_r((tm), &(result))
726#ifndef HAVE_STRUCT_TM_TM_GMTOFF
728rb_gmtime_r(
const time_t *
t,
struct tm *result)
733 struct tm *tmp = gmtime(
t);
734 if (tmp) *result = *tmp;
736#if defined(HAVE_TIMEGM) && defined(LOCALTIME_OVERFLOW_PROBLEM)
737 if (result && *
t != timegm(result)) {
743# define GMTIME(tm, result) rb_gmtime_r((tm), &(result))
746static const int common_year_yday_offset[] = {
751 -1 + 31 + 28 + 31 + 30,
752 -1 + 31 + 28 + 31 + 30 + 31,
753 -1 + 31 + 28 + 31 + 30 + 31 + 30,
754 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31,
755 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
756 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
757 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
758 -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
761static const int leap_year_yday_offset[] = {
766 -1 + 31 + 29 + 31 + 30,
767 -1 + 31 + 29 + 31 + 30 + 31,
768 -1 + 31 + 29 + 31 + 30 + 31 + 30,
769 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31,
770 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
771 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
772 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
773 -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
777static const int common_year_days_in_month[] = {
778 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
780static const int leap_year_days_in_month[] = {
781 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
785 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \
786 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \
787 (m),(m),(m),(m),(m),(m),(m),(m)
789 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \
790 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \
791 (m),(m),(m),(m),(m),(m),(m),(m),(m)
793 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \
794 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \
795 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m)
797 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \
798 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \
799 (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), (m)
801static const uint8_t common_year_mon_of_yday[] = {
805static const uint8_t leap_year_mon_of_yday[] = {
817 10,11,12,13,14,15,16,17,18,19, \
818 20,21,22,23,24,25,26,27,28
821 10,11,12,13,14,15,16,17,18,19, \
822 20,21,22,23,24,25,26,27,28,29
825 10,11,12,13,14,15,16,17,18,19, \
826 20,21,22,23,24,25,26,27,28,29,30
829 10,11,12,13,14,15,16,17,18,19, \
830 20,21,22,23,24,25,26,27,28,29,30,31
832static const uint8_t common_year_mday_of_yday[] = {
834 D31,
D28,
D31,
D30,
D31,
D30,
D31,
D31,
D30,
D31,
D30,
D31
836static const uint8_t leap_year_mday_of_yday[] = {
837 D31,
D29,
D31,
D30,
D31,
D30,
D31,
D31,
D30,
D31,
D30,
D31
846calc_tm_yday(
long tm_year,
int tm_mon,
int tm_mday)
848 int tm_year_mod400 = (
int)
MOD(tm_year, 400);
849 int tm_yday = tm_mday;
851 if (leap_year_p(tm_year_mod400 + 1900))
852 tm_yday += leap_year_yday_offset[tm_mon];
854 tm_yday += common_year_yday_offset[tm_mon];
860timegmw_noleapsecond(
struct vtm *vtm)
870 year1900 = subv(vtm->year,
INT2FIX(1900));
872 divmodv(year1900,
INT2FIX(400), &q400, &r400);
875 yday = calc_tm_yday(year_mod400, vtm->mon-1, vtm->mday);
888 +
DIV(year_mod400 - 69, 4)
889 -
DIV(year_mod400 - 1, 100)
890 + (year_mod400 + 299) / 400;
892 vdays = addv(vdays, mulv(q400,
INT2FIX(97)));
893 vdays = addv(vdays, mulv(year1900,
INT2FIX(365)));
894 wret = wadd(rb_time_magnify(v2w(ret)), wmul(rb_time_magnify(v2w(vdays)),
WINT2FIXWV(86400)));
895 wret = wadd(wret, v2w(vtm->subsecx));
901zone_str(
const char *
zone)
912 for (p =
zone; *p; p++)
928gmtimew_noleapsecond(
wideval_t timew,
struct vtm *vtm)
939 split_second(timew, &timew2, &subsecx);
940 vtm->subsecx = subsecx;
947 vtm->wday = (wday + 4) % 7;
950 vtm->sec = n % 60; n = n / 60;
951 vtm->min = n % 60; n = n / 60;
955 divmodv(timev,
INT2FIX(400*365 + 97), &timev, &v);
956 vtm->year = mulv(timev,
INT2FIX(400));
968 if (30*365+7+31+29-1 <= n) {
982 x = n / (365*100 + 24);
983 n = n % (365*100 + 24);
985 if (30*365+7+31+29-1 <= n) {
998 if (365*2+31+29-1 <= n) {
1014 vtm->year = addv(vtm->year,
INT2NUM(y));
1016 if (leap_year_p(y)) {
1017 vtm->mon = leap_year_mon_of_yday[n];
1018 vtm->mday = leap_year_mday_of_yday[n];
1021 vtm->mon = common_year_mon_of_yday[n];
1022 vtm->mday = common_year_mday_of_yday[n];
1026 vtm->zone = str_utc;
1030gmtime_with_leapsecond(
const time_t *timep,
struct tm *result)
1032#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
1036 int gmtoff_sec, gmtoff_min, gmtoff_hour, gmtoff_day;
1043 if (
t->tm_gmtoff < 0) {
1045 gmtoff = -
t->tm_gmtoff;
1049 gmtoff =
t->tm_gmtoff;
1051 gmtoff_sec = (
int)(gmtoff % 60);
1052 gmtoff = gmtoff / 60;
1053 gmtoff_min = (
int)(gmtoff % 60);
1054 gmtoff = gmtoff / 60;
1055 gmtoff_hour = (
int)gmtoff;
1059 gmtoff_hour *= sign;
1066 result->tm_sec += gmtoff_sec;
1067 if (result->tm_sec < 0) {
1068 result->tm_sec += 60;
1071 if (60 <= result->tm_sec) {
1072 result->tm_sec -= 60;
1077 result->tm_min += gmtoff_min;
1078 if (result->tm_min < 0) {
1079 result->tm_min += 60;
1082 if (60 <= result->tm_min) {
1083 result->tm_min -= 60;
1088 result->tm_hour += gmtoff_hour;
1089 if (result->tm_hour < 0) {
1090 result->tm_hour += 24;
1093 if (24 <= result->tm_hour) {
1094 result->tm_hour -= 24;
1100 if (gmtoff_day < 0) {
1101 if (result->tm_yday == 0) {
1102 result->tm_mday = 31;
1103 result->tm_mon = 11;
1105 result->tm_yday = leap_year_p(result->tm_year + 1900) ? 365 : 364;
1107 else if (result->tm_mday == 1) {
1108 const int *days_in_month = leap_year_p(result->tm_year + 1900) ?
1109 leap_year_days_in_month :
1110 common_year_days_in_month;
1112 result->tm_mday = days_in_month[result->tm_mon];
1119 result->tm_wday = (result->tm_wday + 6) % 7;
1122 int leap = leap_year_p(result->tm_year + 1900);
1123 if (result->tm_yday == (leap ? 365 : 364)) {
1126 result->tm_mday = 1;
1127 result->tm_yday = 0;
1129 else if (result->tm_mday == (leap ? leap_year_days_in_month :
1130 common_year_days_in_month)[result->tm_mon]) {
1132 result->tm_mday = 1;
1139 result->tm_wday = (result->tm_wday + 1) % 7;
1142 result->tm_isdst = 0;
1143 result->tm_gmtoff = 0;
1144#if defined(HAVE_TM_ZONE)
1145 result->tm_zone = (
char *)
"UTC";
1149 return GMTIME(timep, *result);
1153static long this_year = 0;
1154static time_t known_leap_seconds_limit;
1155static int number_of_leap_seconds_known;
1158init_leap_second_info(
void)
1165 if (this_year == 0) {
1167 struct tm *tm, result;
1172 tm = gmtime_with_leapsecond(&now, &result);
1174 this_year = tm->tm_year;
1176 if (TIMET_MAX - now < (time_t)(366*86400))
1177 known_leap_seconds_limit = TIMET_MAX;
1179 known_leap_seconds_limit = now + (time_t)(366*86400);
1181 if (!gmtime_with_leapsecond(&known_leap_seconds_limit, &result))
1184 vtm.year =
LONG2NUM(result.tm_year + 1900);
1185 vtm.mon = result.tm_mon + 1;
1186 vtm.mday = result.tm_mday;
1187 vtm.hour = result.tm_hour;
1188 vtm.min = result.tm_min;
1189 vtm.sec = result.tm_sec;
1193 timew = timegmw_noleapsecond(&vtm);
1195 number_of_leap_seconds_known =
NUM2INT(w2v(wsub(
TIMET2WV(known_leap_seconds_limit), rb_time_unmagnify(timew))));
1207timegmw(
struct vtm *vtm)
1217 return timegmw_noleapsecond(vtm);
1219 init_leap_second_info();
1221 timew = timegmw_noleapsecond(vtm);
1224 if (number_of_leap_seconds_known == 0) {
1230 else if (
wlt(rb_time_magnify(
TIMET2WV(known_leap_seconds_limit)), timew)) {
1231 return wadd(timew, rb_time_magnify(
WINT2WV(number_of_leap_seconds_known)));
1235 tm.tm_mon = vtm->mon - 1;
1236 tm.tm_mday = vtm->mday;
1237 tm.tm_hour = vtm->hour;
1238 tm.tm_min = vtm->min;
1239 tm.tm_sec = vtm->sec;
1242 errmsg = find_time_t(&tm, 1, &
t);
1245 return wadd(rb_time_magnify(
TIMET2WV(
t)), v2w(vtm->subsecx));
1249gmtimew(
wideval_t timew,
struct vtm *result)
1257 gmtimew_noleapsecond(timew, result);
1261 init_leap_second_info();
1263 if (number_of_leap_seconds_known == 0) {
1267 gmtimew_noleapsecond(timew, result);
1270 else if (
wlt(rb_time_magnify(
TIMET2WV(known_leap_seconds_limit)), timew)) {
1271 timew = wsub(timew, rb_time_magnify(
WINT2WV(number_of_leap_seconds_known)));
1272 gmtimew_noleapsecond(timew, result);
1276 split_second(timew, &timew2, &subsecx);
1279 if (!gmtime_with_leapsecond(&
t, &tm))
1282 result->year =
LONG2NUM((
long)tm.tm_year + 1900);
1283 result->mon = tm.tm_mon + 1;
1284 result->mday = tm.tm_mday;
1285 result->hour = tm.tm_hour;
1286 result->min = tm.tm_min;
1287 result->sec = tm.tm_sec;
1288 result->subsecx = subsecx;
1289 result->utc_offset =
INT2FIX(0);
1290 result->wday = tm.tm_wday;
1291 result->yday = tm.tm_yday+1;
1292 result->isdst = tm.tm_isdst;
1300#define GMTIMEW(w, v) \
1301 (gmtimew(w, v) ? (void)0 : rb_raise(rb_eArgError, "gmtime error"))
1303static struct tm *localtime_with_gmtoff_zone(
const time_t *
t,
struct tm *result,
long *gmtoff,
VALUE *
zone);
1338static const int compat_common_month_table[12][7] = {
1340 { 2034, 2035, 2036, 2031, 2032, 2027, 2033 },
1341 { 2026, 2027, 2033, 2034, 2035, 2030, 2031 },
1342 { 2026, 2032, 2033, 2034, 2035, 2030, 2036 },
1343 { 2035, 2030, 2036, 2026, 2032, 2033, 2034 },
1344 { 2033, 2034, 2035, 2030, 2036, 2026, 2032 },
1345 { 2036, 2026, 2032, 2033, 2034, 2035, 2030 },
1346 { 2035, 2030, 2036, 2026, 2032, 2033, 2034 },
1347 { 2032, 2033, 2034, 2035, 2030, 2036, 2026 },
1348 { 2030, 2036, 2026, 2032, 2033, 2034, 2035 },
1349 { 2034, 2035, 2030, 2036, 2026, 2032, 2033 },
1350 { 2026, 2032, 2033, 2034, 2035, 2030, 2036 },
1351 { 2030, 2036, 2026, 2032, 2033, 2034, 2035 },
1379static const int compat_leap_month_table[7] = {
1381 2032, 2016, 2028, 2012, 2024, 2036, 2020,
1385calc_wday(
int year_mod400,
int month,
int day)
1390 a = (14 - month) / 12;
1391 y = year_mod400 + 4800 - a;
1392 m = month + 12 * a - 3;
1393 wday = day + (153*m+2)/5 + 365*y + y/4 - y/100 + y/400 + 2;
1399guess_local_offset(
struct vtm *vtm_utc,
int *isdst_ret,
VALUE *zone_ret)
1407 int year_mod400, wday;
1416# if defined(NEGATIVE_TIME_T)
1417# if SIZEOF_TIME_T <= 4
1419# define THE_TIME_OLD_ENOUGH ((time_t)0x80000000)
1423# define THE_TIME_OLD_ENOUGH ((time_t)(1600-1970)*366*24*60*60)
1425 if (localtime_with_gmtoff_zone((
t = THE_TIME_OLD_ENOUGH, &
t), &tm, &gmtoff, &
zone)) {
1427 isdst = tm.tm_isdst;
1432 if (localtime_with_gmtoff_zone((
t = 0, &
t), &tm, &gmtoff, &
zone)) {
1434 isdst = tm.tm_isdst;
1450 wday = calc_wday(year_mod400, vtm_utc->mon, 1);
1451 if (vtm_utc->mon == 2 && leap_year_p(year_mod400))
1452 vtm2.year =
INT2FIX(compat_leap_month_table[wday]);
1454 vtm2.year =
INT2FIX(compat_common_month_table[vtm_utc->mon-1][wday]);
1456 timev = w2v(rb_time_unmagnify(timegmw(&vtm2)));
1457 t = NUM2TIMET(timev);
1459 if (localtime_with_gmtoff_zone(&
t, &tm, &gmtoff, &
zone)) {
1461 *isdst_ret = tm.tm_isdst;
1469 static time_t now = 0;
1470 static long now_gmtoff = 0;
1471 static int now_isdst = 0;
1472 static VALUE now_zone;
1476 localtime_with_gmtoff_zone(&now, &tm, &now_gmtoff, &
zone);
1477 now_isdst = tm.tm_isdst;
1483 *isdst_ret = now_isdst;
1485 *zone_ret = now_zone;
1491small_vtm_sub(
struct vtm *vtm1,
struct vtm *vtm2)
1495 off = vtm1->sec - vtm2->sec;
1496 off += (vtm1->min - vtm2->min) * 60;
1497 off += (vtm1->hour - vtm2->hour) * 3600;
1498 if (
ne(vtm1->year, vtm2->year))
1499 off +=
lt(vtm1->year, vtm2->year) ? -24*3600 : 24*3600;
1500 else if (vtm1->mon != vtm2->mon)
1501 off += vtm1->mon < vtm2->mon ? -24*3600 : 24*3600;
1502 else if (vtm1->mday != vtm2->mday)
1503 off += vtm1->mday < vtm2->mday ? -24*3600 : 24*3600;
1509timelocalw(
struct vtm *vtm)
1515 struct vtm vtm1, vtm2;
1519 long l =
FIX2LONG(vtm->year) - 1900;
1520 if (l < INT_MIN || INT_MAX < l)
1522 tm.tm_year = (
int)l;
1525 v = subv(vtm->year,
INT2FIX(1900));
1531 tm.tm_mon = vtm->mon-1;
1532 tm.tm_mday = vtm->mday;
1533 tm.tm_hour = vtm->hour;
1534 tm.tm_min = vtm->min;
1535 tm.tm_sec = vtm->sec;
1538 if (find_time_t(&tm, 0, &
t))
1540 return wadd(rb_time_magnify(
TIMET2WV(
t)), v2w(vtm->subsecx));
1543 timew1 = timegmw(vtm);
1545 if (!localtimew(timew1, &vtm1))
1548 n = vtmcmp(vtm, &vtm1);
1550 timew1 = wsub(timew1, rb_time_magnify(
WINT2FIXWV(12*3600)));
1551 if (!localtimew(timew1, &vtm1))
1559 timew1 = wsub(timew1, rb_time_magnify(
WINT2FIXWV(24*3600)));
1560 if (!localtimew(timew1, &vtm1))
1564 timew2 = wadd(timew1, rb_time_magnify(
WINT2FIXWV(24*3600)));
1565 if (!localtimew(timew2, &vtm2))
1568 timew1 = wadd(timew1, rb_time_magnify(v2w(small_vtm_sub(vtm, &vtm1))));
1569 timew2 = wadd(timew2, rb_time_magnify(v2w(small_vtm_sub(vtm, &vtm2))));
1571 if (weq(timew1, timew2))
1574 if (!localtimew(timew1, &vtm1))
1576 if (vtm->hour != vtm1.hour || vtm->min != vtm1.min || vtm->sec != vtm1.sec)
1579 if (!localtimew(timew2, &vtm2))
1581 if (vtm->hour != vtm2.hour || vtm->min != vtm2.min || vtm->sec != vtm2.sec)
1585 return lt(vtm1.utc_offset, vtm2.utc_offset) ? timew2 : timew1;
1587 return lt(vtm1.utc_offset, vtm2.utc_offset) ? timew1 : timew2;
1591localtime_with_gmtoff_zone(
const time_t *
t,
struct tm *result,
long *gmtoff,
VALUE *
zone)
1596#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
1597 *gmtoff = tm.tm_gmtoff;
1606 if (l->tm_year != u->tm_year)
1607 off = l->tm_year < u->tm_year ? -1 : 1;
1608 else if (l->tm_mon != u->tm_mon)
1609 off = l->tm_mon < u->tm_mon ? -1 : 1;
1610 else if (l->tm_mday != u->tm_mday)
1611 off = l->tm_mday < u->tm_mday ? -1 : 1;
1614 off = off * 24 + l->tm_hour - u->tm_hour;
1615 off = off * 60 + l->tm_min - u->tm_min;
1616 off = off * 60 + l->tm_sec - u->tm_sec;
1621#if defined(HAVE_TM_ZONE)
1622 *
zone = zone_str(tm.tm_zone);
1623#elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT)
1624# if RUBY_MSVCRT_VERSION >= 140
1625# define tzname _tzname
1626# define daylight _daylight
1629 *
zone = zone_str(tzname[daylight && tm.tm_isdst]);
1633 strftime(
buf,
sizeof(
buf),
"%Z", &tm);
1646timew_out_of_timet_range(
wideval_t timew)
1649#if WIDEVALUE_IS_WIDER && SIZEOF_TIME_T < SIZEOF_INT64_T
1658#if SIZEOF_TIME_T == SIZEOF_INT64_T
1661 if (~(time_t)0 <= 0) {
1671 timexv = w2v(timew);
1679localtimew(
wideval_t timew,
struct vtm *result)
1685 if (!timew_out_of_timet_range(timew)) {
1691 split_second(timew, &timew2, &subsecx);
1695 if (localtime_with_gmtoff_zone(&
t, &tm, &gmtoff, &
zone)) {
1696 result->year =
LONG2NUM((
long)tm.tm_year + 1900);
1697 result->mon = tm.tm_mon + 1;
1698 result->mday = tm.tm_mday;
1699 result->hour = tm.tm_hour;
1700 result->min = tm.tm_min;
1701 result->sec = tm.tm_sec;
1702 result->subsecx = subsecx;
1703 result->wday = tm.tm_wday;
1704 result->yday = tm.tm_yday+1;
1705 result->isdst = tm.tm_isdst;
1706 result->utc_offset =
LONG2NUM(gmtoff);
1707 result->zone =
zone;
1712 if (!gmtimew(timew, result))
1715 offset = guess_local_offset(result, &isdst, &
zone);
1717 if (!gmtimew(wadd(timew, rb_time_magnify(v2w(
offset))), result))
1720 result->utc_offset =
offset;
1721 result->isdst = isdst;
1722 result->zone =
zone;
1727#define TIME_TZMODE_LOCALTIME 0
1728#define TIME_TZMODE_UTC 1
1729#define TIME_TZMODE_FIXOFF 2
1730#define TIME_TZMODE_UNINITIALIZED 3
1735 unsigned int tzmode:3;
1736 unsigned int tm_got:1;
1739#define GetTimeval(obj, tobj) ((tobj) = get_timeval(obj))
1740#define GetNewTimeval(obj, tobj) ((tobj) = get_new_timeval(obj))
1742#define IsTimeval(obj) rb_typeddata_is_kind_of((obj), &time_data_type)
1743#define TIME_INIT_P(tobj) ((tobj)->tzmode != TIME_TZMODE_UNINITIALIZED)
1745#define TZMODE_UTC_P(tobj) ((tobj)->tzmode == TIME_TZMODE_UTC)
1746#define TZMODE_SET_UTC(tobj) ((tobj)->tzmode = TIME_TZMODE_UTC)
1748#define TZMODE_LOCALTIME_P(tobj) ((tobj)->tzmode == TIME_TZMODE_LOCALTIME)
1749#define TZMODE_SET_LOCALTIME(tobj) ((tobj)->tzmode = TIME_TZMODE_LOCALTIME)
1751#define TZMODE_FIXOFF_P(tobj) ((tobj)->tzmode == TIME_TZMODE_FIXOFF)
1752#define TZMODE_SET_FIXOFF(tobj, off) \
1753 ((tobj)->tzmode = TIME_TZMODE_FIXOFF, \
1754 (tobj)->vtm.utc_offset = (off))
1756#define TZMODE_COPY(tobj1, tobj2) \
1757 ((tobj1)->tzmode = (tobj2)->tzmode, \
1758 (tobj1)->vtm.utc_offset = (tobj2)->vtm.utc_offset, \
1759 (tobj1)->vtm.zone = (tobj2)->vtm.zone)
1761static VALUE time_get_tm(
VALUE,
struct time_object *);
1762#define MAKE_TM(time, tobj) \
1764 if ((tobj)->tm_got == 0) { \
1765 time_get_tm((time), (tobj)); \
1768#define MAKE_TM_ENSURE(time, tobj, cond) \
1770 MAKE_TM(time, tobj); \
1772 VALUE zone = (tobj)->vtm.zone; \
1773 if (!NIL_P(zone)) zone_localtime(zone, (time)); \
1780 struct time_object *tobj =
ptr;
1790time_memsize(
const void *tobj)
1792 return sizeof(
struct time_object);
1802time_s_alloc(
VALUE klass)
1805 struct time_object *tobj;
1811 tobj->vtm.zone =
Qnil;
1816static struct time_object *
1817get_timeval(
VALUE obj)
1819 struct time_object *tobj;
1827static struct time_object *
1828get_new_timeval(
VALUE obj)
1830 struct time_object *tobj;
1839time_modify(
VALUE time)
1862 if (timew_out_of_timet_range(timew))
1864 split_second(timew, &timew2, &subsecx);
1877 if (timew_out_of_timet_range(timew))
1879 split_second(timew, &timew2, &subsecx);
1891#ifdef HAVE_CLOCK_GETTIME
1908time_init_0(
VALUE time)
1910 struct time_object *tobj;
1919 tobj->timew = timespec2timew(&ts);
1927 struct time_object *tobj;
1928 off = num_exact(off);
1934 tobj->vtm.zone =
Qnil;
1941vtm_add_offset(
struct vtm *vtm,
VALUE off,
int sign)
1951 divmodv(off,
INT2FIX(1), &off, &subsec);
1952 divmodv(off,
INT2FIX(60), &off, &v);
1954 divmodv(off,
INT2FIX(60), &off, &v);
1956 divmodv(off,
INT2FIX(24), &off, &v);
1960 subsec =
neg(subsec);
1969 vtm->subsecx = addv(vtm->subsecx, w2v(rb_time_magnify(v2w(subsec))));
2020 if (vtm->mon == 1 && vtm->mday == 1) {
2023 vtm->year = subv(vtm->year,
INT2FIX(1));
2026 else if (vtm->mday == 1) {
2028 leap_year_days_in_month :
2029 common_year_days_in_month;
2031 vtm->mday = days_in_month[vtm->mon-1];
2038 vtm->wday = (vtm->wday + 6) % 7;
2042 if (vtm->mon == 12 && vtm->mday == 31) {
2043 vtm->year = addv(vtm->year,
INT2FIX(1));
2048 else if (vtm->mday == (leap ? leap_year_days_in_month :
2049 common_year_days_in_month)[vtm->mon-1]) {
2058 vtm->wday = (vtm->wday + 1) % 7;
2064maybe_tzobj_p(
VALUE obj)
2072NORETURN(
static void invalid_utc_offset(
void));
2074invalid_utc_offset(
void)
2076 static const char message[] =
"\"+HH:MM\", \"-HH:MM\", \"UTC\" "
2077 "or \"A\"..\"I\",\"K\"..\"Z\" expected for utc_offset";
2083utc_offset_arg(
VALUE arg)
2090 goto invalid_utc_offset;
2098 if (s[0] >=
'A' && s[0] <=
'I') {
2099 n = (
int)s[0] -
'A' + 1;
2101 else if (s[0] >=
'K' && s[0] <=
'M') {
2102 n = (
int)s[0] -
'A';
2104 else if (s[0] >=
'N' && s[0] <=
'Y') {
2105 n =
'M' - (
int)s[0];
2108 goto invalid_utc_offset;
2116 goto invalid_utc_offset;
2118 if (s[6] !=
':')
goto invalid_utc_offset;
2120 n += (s[7] * 10 + s[8] -
'0' * 11);
2123 if (s[0] !=
'+' && s[0] !=
'-')
goto invalid_utc_offset;
2125 if (s[3] !=
':')
goto invalid_utc_offset;
2127 if (s[4] >
'5')
goto invalid_utc_offset;
2130 goto invalid_utc_offset;
2132 n += (s[1] * 10 + s[2] -
'0' * 11) * 3600;
2133 n += (s[4] * 10 + s[5] -
'0' * 11) * 60;
2139 return num_exact(arg);
2146zone_set_offset(
VALUE zone,
struct time_object *tobj,
2152 validate_utc_offset(off);
2153 tobj->vtm.utc_offset = off;
2154 tobj->vtm.zone =
zone;
2159extract_time(
VALUE time)
2164#define EXTRACT_TIME() do { \
2165 t = v2w(rb_Integer(AREF(to_i))); \
2169 struct time_object *tobj =
DATA_PTR(time);
2172 t = rb_time_unmagnify(tobj->timew);
2174 else if (RB_TYPE_P(time,
T_STRUCT)) {
2175#define AREF(x) rb_struct_aref(time, ID2SYM(id_##x))
2180#define AREF(x) rb_funcallv(time, id_##x, 0, 0)
2190extract_vtm(
VALUE time,
struct vtm *vtm,
VALUE subsecx)
2195#define EXTRACT_VTM() do { \
2197 vtm->year = obj2vint(AREF(year)); \
2198 vtm->mon = month_arg(AREF(mon)); \
2199 vtm->mday = obj2ubits(AREF(mday), 5); \
2200 vtm->hour = obj2ubits(AREF(hour), 5); \
2201 vtm->min = obj2ubits(AREF(min), 6); \
2202 vtm->sec = obj2subsecx(AREF(sec), &subsecx); \
2203 vtm->isdst = RTEST(AREF(isdst)); \
2204 vtm->utc_offset = Qnil; \
2205 t = v2w(rb_Integer(AREF(to_i))); \
2209 struct time_object *tobj =
DATA_PTR(time);
2211 time_get_tm(time, tobj);
2213 t = rb_time_unmagnify(tobj->timew);
2215 t = wadd(
t, v2w(vtm->utc_offset));
2217 else if (RB_TYPE_P(time,
T_STRUCT)) {
2218#define AREF(x) rb_struct_aref(time, ID2SYM(id_##x))
2222 else if (rb_integer_type_p(time)) {
2227#define AREF(x) rb_funcallv(time, id_##x, 0, 0)
2232 vtm->subsecx = subsecx;
2251 struct time_object *tobj =
DATA_PTR(time);
2254 t = rb_time_unmagnify(tobj->timew);
2255 tm = tm_from_time(rb_cTimeTM, time);
2257 if (utc ==
Qundef)
return 0;
2259 s = extract_time(utc);
2260 zone_set_offset(
zone, tobj,
t, s);
2261 s = rb_time_magnify(s);
2262 if (tobj->vtm.subsecx !=
INT2FIX(0)) {
2263 s = wadd(s, v2w(tobj->vtm.subsecx));
2266 zone_set_dst(
zone, tobj, tm);
2274 struct time_object *tobj =
DATA_PTR(time);
2277 split_second(tobj->timew, &
t, &subsecx);
2278 tm = tm_from_time(rb_cTimeTM, time);
2283 s = extract_vtm(
local, &tobj->vtm, subsecx);
2285 zone_set_offset(
zone, tobj, s,
t);
2286 zone_set_dst(
zone, tobj, tm);
2305 struct time_object *tobj;
2309 vtm.zone = str_empty;
2314 vtm.year = obj2vint(v[0]);
2316 vtm.mon =
NIL_P(v[1]) ? 1 : month_arg(v[1]);
2318 vtm.mday =
NIL_P(v[2]) ? 1 : obj2ubits(v[2], 5);
2320 vtm.hour =
NIL_P(v[3]) ? 0 : obj2ubits(v[3], 5);
2322 vtm.min =
NIL_P(v[4]) ? 0 : obj2ubits(v[4], 6);
2330 vtm.sec = obj2subsecx(v[5], &subsecx);
2331 vtm.subsecx = subsecx;
2335 vtm.utc_offset =
Qnil;
2342 else if (maybe_tzobj_p(arg))
2344 else if (!
NIL_P(utc = utc_offset_arg(arg)))
2346 else if (
NIL_P(
zone = find_timezone(time, arg)))
2347 invalid_utc_offset();
2356 tobj->timew = timegmw(&vtm);
2360 if (zone_timelocal(
zone, time)) {
2363 else if (
NIL_P(vtm.utc_offset = utc_offset_arg(
zone))) {
2365 invalid_utc_offset();
2370 tobj->timew = timegmw(&vtm);
2381 if (!
NIL_P(vtm.utc_offset)) {
2382 VALUE off = vtm.utc_offset;
2383 vtm_add_offset(&vtm, off, -1);
2384 vtm.utc_offset =
Qnil;
2385 tobj->timew = timegmw(&vtm);
2386 return time_set_utc_offset(time, off);
2389 tobj->timew = timelocalw(&vtm);
2390 return time_localtime(time);
2447 return time_init_0(time);
2449 return time_init_1(
argc,
argv, time);
2453time_overflow_p(time_t *secp,
long *nsecp)
2459 if (nsec >= 1000000000) {
2460 sec2 = nsec / 1000000000;
2461 if (TIMET_MAX - sec2 < sec) {
2464 nsec -= sec2 * 1000000000;
2467 else if (nsec < 0) {
2468 sec2 =
NDIV(nsec,1000000000);
2469 if (sec < TIMET_MIN - sec2) {
2472 nsec -= sec2 * 1000000000;
2475#ifndef NEGATIVE_TIME_T
2484nsec2timew(time_t sec,
long nsec)
2487 time_overflow_p(&sec, &nsec);
2490 return timespec2timew(&ts);
2496 VALUE time = time_s_alloc(klass);
2497 struct time_object *tobj;
2501 tobj->timew = timew;
2511 if (usec >= 1000000) {
2512 long sec2 = usec / 1000000;
2513 if (sec > TIMET_MAX - sec2) {
2516 usec -= sec2 * 1000000;
2519 else if (usec < 0) {
2520 long sec2 =
NDIV(usec,1000000);
2521 if (sec < TIMET_MIN - sec2) {
2524 usec -= sec2 * 1000000;
2528 timew = nsec2timew(sec, usec * 1000);
2529 return time_new_timew(
rb_cTime, timew);
2536 return time_new_timew(
rb_cTime, nsec2timew(sec, nsec));
2547 struct time_object *tobj;
2554 else if (
offset == INT_MAX) {
2556 else if (
offset == INT_MAX-1) {
2570 VALUE time = time_new_timew(
rb_cTime, rb_time_magnify(v2w(timev)));
2575 if (maybe_tzobj_p(
zone)) {
2577 if (zone_timelocal(
zone, time))
return time;
2579 if (
NIL_P(off = utc_offset_arg(off))) {
2580 if (
NIL_P(
zone = find_timezone(time,
zone))) invalid_utc_offset();
2582 if (!zone_timelocal(
zone, time)) invalid_utc_offset();
2586 return time_gmtime(time);
2589 validate_utc_offset(off);
2590 time_set_utc_offset(time, off);
2601 const char *
const tstr = interval ?
"time interval" :
"time";
2604#ifndef NEGATIVE_TIME_T
2605# define arg_range_check(v) \
2607 rb_raise(rb_eArgError, "%s must not be negative", tstr) : \
2610# define arg_range_check(v) \
2611 ((interval && (v) < 0) ? \
2612 rb_raise(rb_eArgError, "time interval must not be negative") : \
2617 t.tv_sec = NUM2TIMET(
num);
2621 else if (RB_FLOAT_TYPE_P(
num)) {
2629 t.tv_nsec = (
int)(d*1e9+0.5);
2630 if (
t.tv_nsec >= 1000000000) {
2631 t.tv_nsec -= 1000000000;
2635 else if ((
t.tv_nsec = (
int)(-d*1e9+0.5)) > 0) {
2636 t.tv_nsec = 1000000000 -
t.tv_nsec;
2639 t.tv_sec = (time_t)
f;
2640 if (
f !=
t.tv_sec) {
2646 t.tv_sec = NUM2TIMET(
num);
2656 t.tv_sec = NUM2TIMET(i);
2667#undef arg_range_check
2676 ts = time_timespec(
num, interval);
2686 return time_timeval(
num,
TRUE);
2692 struct time_object *tobj;
2698 ts = timew2timespec(tobj->timew);
2703 return time_timeval(time,
FALSE);
2709 struct time_object *tobj;
2714 t = timew2timespec(tobj->timew);
2717 return time_timespec(time,
FALSE);
2723 return time_timespec(
num,
TRUE);
2736 if (
NIL_P(opts))
return false;
2760 time_zonelocal(
t,
zone);
2766get_scale(
VALUE unit)
2768 if (unit ==
ID2SYM(id_nanosecond) || unit ==
ID2SYM(id_nsec)) {
2771 else if (unit ==
ID2SYM(id_microsecond) || unit ==
ID2SYM(id_usec)) {
2774 else if (unit ==
ID2SYM(id_millisecond)) {
2839 if (get_tmopt(opts, vals)) {
2843 int scale =
argc == 3 ? get_scale(unit) : 1000000;
2844 time = num_exact(time);
2847 t = time_new_timew(klass, timew);
2850 struct time_object *tobj, *tobj2;
2852 t = time_new_timew(klass, tobj->timew);
2857 timew = rb_time_magnify(v2w(num_exact(time)));
2858 t = time_new_timew(klass, timew);
2861 time_zonelocal(
t,
zone);
2867static const char months[][4] = {
2868 "jan",
"feb",
"mar",
"apr",
"may",
"jun",
2869 "jul",
"aug",
"sep",
"oct",
"nov",
"dec",
2886 const unsigned int usable_mask = (1U <<
bits) - 1;
2887 unsigned int rv = (
unsigned int)obj2int(obj);
2889 if ((rv & usable_mask) != rv)
2917 divmodv(num_exact(obj),
INT2FIX(1), &obj, &subsec);
2918 *subsecx = w2v(rb_time_magnify(v2w(subsec)));
2920 return obj2ubits(obj, 6);
2924usec2subsecx(
VALUE obj)
2939 return obj2ubits(arg, 4);
2945 for (i=0; i<12; i++) {
2955 if (
'0' <= c && c <=
'9') {
2956 mon = obj2ubits(s, 4);
2961 mon = obj2ubits(arg, 4);
2967validate_utc_offset(
VALUE utc_offset)
2975validate_zone_name(
VALUE zone_name)
2982validate_vtm(
struct vtm *vtm)
2984#define validate_vtm_range(mem, b, e) \
2985 ((vtm->mem < b || vtm->mem > e) ? \
2986 rb_raise(rb_eArgError, #mem" out of range") : (void)0)
2994 if (!
NIL_P(vtm->utc_offset)) validate_utc_offset(vtm->utc_offset);
2995#undef validate_vtm_range
3011 vtm->utc_offset =
Qnil;
3015 vtm->zone = str_empty;
3028 rb_scan_args(
argc,
argv,
"17", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6],&v[7]);
3035 vtm->year = obj2vint(v[0]);
3041 vtm->mon = month_arg(v[1]);
3048 vtm->mday = obj2ubits(v[2], 5);
3057 if (vtm->mday > mday2) {
3067 if (vtm->mday == 31) {
3074 vtm->hour =
NIL_P(v[3])?0:obj2ubits(v[3], 5);
3076 vtm->min =
NIL_P(v[4])?0:obj2ubits(v[4], 6);
3079 vtm->sec =
NIL_P(v[5])?0:obj2ubits(v[5],6);
3080 subsecx = usec2subsecx(v[6]);
3088 vtm->sec = obj2subsecx(v[5], &subsecx);
3091 vtm->subsecx = subsecx;
3103 unsigned long uy = (
unsigned long)(
LIKELY(y >= 0) ? y : -y);
3105 if (
LIKELY(uy % 4 != 0))
return 0;
3107 unsigned long century = uy / 100;
3108 if (
LIKELY(uy != century * 100))
return 1;
3109 return century % 4 == 0;
3113timegm_noleapsecond(
struct tm *tm)
3115 long tm_year = tm->tm_year;
3116 int tm_yday = calc_tm_yday(tm->tm_year, tm->tm_mon, tm->tm_mday);
3124 return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 +
3128 DIV(tm_year-1,100) +
3129 DIV(tm_year+299,400))*86400;
3133#define DEBUG_FIND_TIME_NUMGUESS
3134#define DEBUG_GUESSRANGE
3137#ifdef DEBUG_GUESSRANGE
3138#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))
3140#define DEBUG_REPORT_GUESSRANGE
3143#ifdef DEBUG_FIND_TIME_NUMGUESS
3144#define DEBUG_FIND_TIME_NUMGUESS_INC find_time_numguess++,
3145static unsigned long long find_time_numguess;
3147static VALUE find_time_numguess_getter(
void)
3149 return ULL2NUM(find_time_numguess);
3152#define DEBUG_FIND_TIME_NUMGUESS_INC
3156find_time_t(
struct tm *tptr,
int utc_p, time_t *tp)
3158 time_t guess, guess0, guess_lo, guess_hi;
3159 struct tm *tm, tm0, tm_lo, tm_hi;
3166#define GUESS(p) (DEBUG_FIND_TIME_NUMGUESS_INC (utc_p ? gmtime_with_leapsecond((p), &result) : LOCALTIME((p), result)))
3168 guess_lo = TIMET_MIN;
3169 guess_hi = TIMET_MAX;
3171 find_dst = 0 < tptr->tm_isdst;
3177 if (tm0.tm_mon < 0) {
3184 else if (11 < tm0.tm_mon) {
3191 else if (tm0.tm_mday < 1) {
3197 else if ((d = (leap_year_p(1900 + tm0.tm_year) ?
3198 leap_year_days_in_month :
3199 common_year_days_in_month)[tm0.tm_mon]) < tm0.tm_mday) {
3205 else if (tm0.tm_hour < 0) {
3210 else if (23 < tm0.tm_hour) {
3215 else if (tm0.tm_min < 0) {
3219 else if (59 < tm0.tm_min) {
3223 else if (tm0.tm_sec < 0) {
3226 else if (60 < tm0.tm_sec) {
3231 guess0 = guess = timegm_noleapsecond(&tm0);
3234 d = tmcmp(tptr, tm);
3235 if (d == 0) {
goto found; }
3238 guess -= 24 * 60 * 60;
3242 guess += 24 * 60 * 60;
3245 if (guess_lo < guess && guess < guess_hi && (tm =
GUESS(&guess)) !=
NULL) {
3246 d = tmcmp(tptr, tm);
3247 if (d == 0) {
goto found; }
3256 tm =
GUESS(&guess_lo);
3257 if (!tm)
goto error;
3258 d = tmcmp(tptr, tm);
3259 if (d < 0)
goto out_of_range;
3260 if (d == 0) { guess = guess_lo;
goto found; }
3263 tm =
GUESS(&guess_hi);
3264 if (!tm)
goto error;
3265 d = tmcmp(tptr, tm);
3266 if (d > 0)
goto out_of_range;
3267 if (d == 0) { guess = guess_hi;
goto found; }
3274 while (guess_lo + 1 < guess_hi) {
3277 guess = guess_lo / 2 + guess_hi / 2;
3278 if (guess <= guess_lo)
3279 guess = guess_lo + 1;
3280 else if (guess >= guess_hi)
3281 guess = guess_hi - 1;
3286 time_t guess0_hi = timegm_noleapsecond(&tm_hi);
3287 guess = guess_hi - (guess0_hi - guess0);
3288 if (guess == guess_hi)
3292 else if (status == 2) {
3293 time_t guess0_lo = timegm_noleapsecond(&tm_lo);
3294 guess = guess_lo + (guess0 - guess0_lo);
3295 if (guess == guess_lo)
3299 if (guess <= guess_lo || guess_hi <= guess) {
3301#ifdef DEBUG_GUESSRANGE
3302 if (guess <= guess_lo) fprintf(stderr,
"too small guess: %ld <= %ld\n", guess, guess_lo);
3303 if (guess_hi <= guess) fprintf(stderr,
"too big guess: %ld <= %ld\n", guess_hi, guess);
3311 if (!tm)
goto error;
3313 d = tmcmp(tptr, tm);
3338 tptr_tm_yday = calc_tm_yday(tptr->tm_year, tptr->tm_mon, tptr->tm_mday);
3341 ((tptr->tm_year - tm_lo.tm_year) * 365 +
3342 DIV((tptr->tm_year-69), 4) -
3343 DIV((tptr->tm_year-1), 100) +
3344 DIV((tptr->tm_year+299), 400) -
3345 DIV((tm_lo.tm_year-69), 4) +
3346 DIV((tm_lo.tm_year-1), 100) -
3347 DIV((tm_lo.tm_year+299), 400) +
3349 tm_lo.tm_yday) * 86400 +
3350 (tptr->tm_hour - tm_lo.tm_hour) * 3600 +
3351 (tptr->tm_min - tm_lo.tm_min) * 60 +
3352 (tptr->tm_sec - (tm_lo.tm_sec == 60 ? 59 : tm_lo.tm_sec));
3361 guess2 = guess - 2 * 60 * 60;
3364 if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
3365 tptr->tm_min != tm->tm_min ||
3366 tptr->tm_sec != tm->tm_sec) {
3367 guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
3368 (tm->tm_min - tptr->tm_min) * 60 +
3369 (tm->tm_sec - tptr->tm_sec);
3370 if (tptr->tm_mday != tm->tm_mday)
3371 guess2 += 24 * 60 * 60;
3372 if (guess != guess2) {
3374 if (tm && tmcmp(tptr, tm) == 0) {
3386 guess2 = guess + 2 * 60 * 60;
3389 if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
3390 tptr->tm_min != tm->tm_min ||
3391 tptr->tm_sec != tm->tm_sec) {
3392 guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
3393 (tm->tm_min - tptr->tm_min) * 60 +
3394 (tm->tm_sec - tptr->tm_sec);
3395 if (tptr->tm_mday != tm->tm_mday)
3396 guess2 -= 24 * 60 * 60;
3397 if (guess != guess2) {
3399 if (tm && tmcmp(tptr, tm) == 0) {
3415 return "time out of range";
3418 return "gmtime/localtime error";
3422vtmcmp(
struct vtm *a,
struct vtm *b)
3424 if (
ne(a->year, b->year))
3425 return lt(a->year, b->year) ? -1 : 1;
3426 else if (a->mon != b->mon)
3427 return a->mon < b->mon ? -1 : 1;
3428 else if (a->mday != b->mday)
3429 return a->mday < b->mday ? -1 : 1;
3430 else if (a->hour != b->hour)
3431 return a->hour < b->hour ? -1 : 1;
3432 else if (a->min != b->min)
3433 return a->min < b->min ? -1 : 1;
3434 else if (a->sec != b->sec)
3435 return a->sec < b->sec ? -1 : 1;
3436 else if (
ne(a->subsecx, b->subsecx))
3437 return lt(a->subsecx, b->subsecx) ? -1 : 1;
3443tmcmp(
struct tm *a,
struct tm *b)
3445 if (a->tm_year != b->tm_year)
3446 return a->tm_year < b->tm_year ? -1 : 1;
3447 else if (a->tm_mon != b->tm_mon)
3448 return a->tm_mon < b->tm_mon ? -1 : 1;
3449 else if (a->tm_mday != b->tm_mday)
3450 return a->tm_mday < b->tm_mday ? -1 : 1;
3451 else if (a->tm_hour != b->tm_hour)
3452 return a->tm_hour < b->tm_hour ? -1 : 1;
3453 else if (a->tm_min != b->tm_min)
3454 return a->tm_min < b->tm_min ? -1 : 1;
3455 else if (a->tm_sec != b->tm_sec)
3456 return a->tm_sec < b->tm_sec ? -1 : 1;
3499 return time_gmtime(time_new_timew(klass, timegmw(&vtm)));
3533 return time_localtime(time_new_timew(klass, timelocalw(&vtm)));
3551time_to_i(
VALUE time)
3553 struct time_object *tobj;
3584time_to_f(
VALUE time)
3586 struct time_object *tobj;
3589 return rb_Float(rb_time_unmagnify_to_float(tobj->timew));
3607time_to_r(
VALUE time)
3609 struct time_object *tobj;
3613 v = rb_time_unmagnify_to_rational(tobj->timew);
3641time_usec(
VALUE time)
3643 struct time_object *tobj;
3674time_nsec(
VALUE time)
3676 struct time_object *tobj;
3704time_subsec(
VALUE time)
3706 struct time_object *tobj;
3740 struct time_object *tobj1, *tobj2;
3746 n = wcmp(tobj1->timew, tobj2->timew);
3751 if (n == 0)
return INT2FIX(0);
3767 struct time_object *tobj1, *tobj2;
3772 return rb_equal(w2v(tobj1->timew), w2v(tobj2->timew));
3796time_utc_p(
VALUE time)
3798 struct time_object *tobj;
3815time_hash(
VALUE time)
3817 struct time_object *tobj;
3820 return rb_hash(w2v(tobj->timew));
3827 struct time_object *tobj, *tcopy;
3832 MEMCPY(tcopy, tobj,
struct time_object, 1);
3841 time_init_copy(dup, time);
3846time_localtime(
VALUE time)
3848 struct time_object *tobj;
3861 zone = tobj->vtm.zone;
3862 if (maybe_tzobj_p(
zone) && zone_localtime(
zone, time)) {
3866 if (!localtimew(tobj->timew, &vtm))
3879 if (zone_localtime(
zone, time))
return time;
3881 if (
NIL_P(off = utc_offset_arg(off))) {
3882 if (
NIL_P(
zone = find_timezone(time,
zone))) invalid_utc_offset();
3883 if (!zone_localtime(
zone, time)) invalid_utc_offset();
3887 return time_gmtime(time);
3889 validate_utc_offset(off);
3891 time_set_utc_offset(time, off);
3892 return time_fixoff(time);
3924 return time_zonelocal(time, off);
3927 return time_localtime(time);
3949time_gmtime(
VALUE time)
3951 struct time_object *tobj;
3973time_fixoff(
VALUE time)
3975 struct time_object *tobj;
3989 off = tobj->vtm.utc_offset;
3995 zone = tobj->vtm.zone;
3997 tobj->vtm.zone =
zone;
3998 vtm_add_offset(&tobj->vtm, off, +1);
4041 if (maybe_tzobj_p(
zone)) {
4042 VALUE t = time_dup(time);
4043 if (zone_localtime(off,
t))
return t;
4046 if (
NIL_P(off = utc_offset_arg(off))) {
4047 if (
NIL_P(
zone = find_timezone(time,
zone))) invalid_utc_offset();
4048 time = time_dup(time);
4049 if (!zone_localtime(
zone, time)) invalid_utc_offset();
4053 return time_gmtime(time_dup(time));
4055 validate_utc_offset(off);
4057 time = time_dup(time);
4058 time_set_utc_offset(time, off);
4059 return time_fixoff(time);
4062 return time_localtime(time_dup(time));
4080time_getgmtime(
VALUE time)
4082 return time_gmtime(time_dup(time));
4086time_get_tm(
VALUE time,
struct time_object *tobj)
4090 return time_localtime(time);
4094#define strftimev(fmt, time, enc) strftime_cstr((fmt), rb_strlen_lit(fmt), (time), (enc))
4108time_asctime(
VALUE time)
4129time_to_s(
VALUE time)
4131 struct time_object *tobj;
4156time_inspect(
VALUE time)
4158 struct time_object *tobj;
4191 struct time_object *result_tobj;
4195 result = time_new_timew(klass, wsub(tobj->timew, rb_time_magnify(v2w(
offset))));
4197 result = time_new_timew(klass, wadd(tobj->timew, rb_time_magnify(v2w(
offset))));
4205time_add(
const struct time_object *tobj,
VALUE torig,
VALUE offset,
int sign)
4224 struct time_object *tobj;
4230 return time_add(tobj, time1, time2, 1);
4251 struct time_object *tobj;
4255 struct time_object *tobj2;
4258 return rb_Float(rb_time_unmagnify_to_float(wsub(tobj->timew, tobj2->timew)));
4260 return time_add(tobj, time1, time2, -1);
4264ndigits_denominator(
VALUE ndigits)
4310 VALUE ndigits, v, den;
4311 struct time_object *tobj;
4316 den = ndigits_denominator(ndigits);
4319 v = w2v(rb_time_unmagnify(tobj->timew));
4323 return time_add(tobj, time, v, -1);
4325 return time_add(tobj, time, subv(den, v), 1);
4358 VALUE ndigits, v, den;
4359 struct time_object *tobj;
4364 den = ndigits_denominator(ndigits);
4367 v = w2v(rb_time_unmagnify(tobj->timew));
4370 return time_add(tobj, time, v, -1);
4403 VALUE ndigits, v, den;
4404 struct time_object *tobj;
4409 den = ndigits_denominator(ndigits);
4412 v = w2v(rb_time_unmagnify(tobj->timew));
4418 return time_add(tobj, time, v, 1);
4438 struct time_object *tobj;
4442 return INT2FIX(tobj->vtm.sec);
4458 struct time_object *tobj;
4462 return INT2FIX(tobj->vtm.min);
4476time_hour(
VALUE time)
4478 struct time_object *tobj;
4482 return INT2FIX(tobj->vtm.hour);
4498time_mday(
VALUE time)
4500 struct time_object *tobj;
4504 return INT2FIX(tobj->vtm.mday);
4522 struct time_object *tobj;
4526 return INT2FIX(tobj->vtm.mon);
4540time_year(
VALUE time)
4542 struct time_object *tobj;
4546 return tobj->vtm.year;
4568time_wday(
VALUE time)
4570 struct time_object *tobj;
4574 return INT2FIX((
int)tobj->vtm.wday);
4578 return (time_wday(time) == INT2FIX(n)) ? Qtrue : Qfalse; \
4592time_sunday(
VALUE time)
4608time_monday(
VALUE time)
4624time_tuesday(
VALUE time)
4640time_wednesday(
VALUE time)
4656time_thursday(
VALUE time)
4672time_friday(
VALUE time)
4688time_saturday(
VALUE time)
4704time_yday(
VALUE time)
4706 struct time_object *tobj;
4710 return INT2FIX(tobj->vtm.yday);
4739time_isdst(
VALUE time)
4741 struct time_object *tobj;
4765time_zone(
VALUE time)
4767 struct time_object *tobj;
4776 zone = tobj->vtm.zone;
4803 struct time_object *tobj;
4812 return tobj->vtm.utc_offset;
4834time_to_a(
VALUE time)
4836 struct time_object *tobj;
4854rb_strftime_alloc(
const char *format,
size_t format_len,
rb_encoding *enc,
4860 if (!timew2timespec_exact(timew, &ts))
4861 timev = w2v(rb_time_unmagnify(timew));
4867 return rb_strftime(format, format_len, enc, time, vtm, timev, gmt);
4874 struct time_object *tobj;
4879 str = rb_strftime_alloc(fmt,
len, enc, time, &tobj->vtm, tobj->timew,
TZMODE_UTC_P(tobj));
5074 struct time_object *tobj;
5091 rb_warning(
"strftime called with empty format string");
5095 VALUE str = rb_strftime_alloc(fmt,
len, enc, time, &tobj->vtm, tobj->timew,
5109time_mdump(
VALUE time)
5111 struct time_object *tobj;
5123 const int max_year = 1900+0xffff;
5127 gmtimew(tobj->timew, &vtm);
5131 if (year > max_year) {
5132 year_extend =
INT2FIX(year - max_year);
5135 else if (year < 1900) {
5136 year_extend =
LONG2NUM(1900 - year);
5151 subsecx = vtm.subsecx;
5154 divmodv(nano,
INT2FIX(1), &v, &subnano);
5159 nano = addv(
LONG2FIX(nsec), subnano);
5167 s = (
unsigned long)vtm.min << 26 |
5171 for (i=0; i<4; i++) {
5172 buf[i] = (
unsigned char)p;
5175 for (i=4; i<8; i++) {
5176 buf[i] = (
unsigned char)s;
5180 if (!
NIL_P(year_extend)) {
5192 (year == 1900 ?
"small" :
"big"), vtm.year);
5225 buf[1] = (char)((nsec % 10) << 4);
5227 buf[0] = (char)(nsec % 10);
5229 buf[0] |= (char)((nsec % 10) << 4);
5241 zone = tobj->vtm.zone;
5242 if (maybe_tzobj_p(
zone)) {
5256 str = time_mdump(time);
5262mload_findzone(
VALUE arg)
5266 return find_timezone(time,
zone);
5287 struct time_object *tobj;
5300#define get_attr(attr, iffound) \
5301 attr = rb_attr_delete(str, id_##attr); \
5302 if (!NIL_P(attr)) { \
5320 goto invalid_format;
5324 for (i=0; i<4; i++) {
5325 p |= (
unsigned long)
buf[i]<<(8*i);
5327 for (i=4; i<8; i++) {
5328 s |= (
unsigned long)
buf[i]<<(8*(i-4));
5331 if ((p & (1UL<<31)) == 0) {
5341 gmt = (
int)((p >> 30) & 0x1);
5344 year =
INT2FIX(((
int)(p >> 14) & 0xffff) + 1900);
5352 len -= ybuf - (
const char *)
buf;
5353 if (ysize < 0 || ysize >
len)
goto invalid_format;
5363 vtm.mon = ((
int)(p >> 10) & 0xf) + 1;
5364 vtm.mday = (
int)(p >> 5) & 0x1f;
5365 vtm.hour = (
int) p & 0x1f;
5366 vtm.min = (
int)(s >> 26) & 0x3f;
5367 vtm.sec = (
int)(s >> 20) & 0x3f;
5369 vtm.yday = vtm.wday = 0;
5371 vtm.zone = str_empty;
5373 usec = (
long)(s & 0xfffff);
5378 if (nano_num !=
Qnil) {
5379 VALUE nano = quov(num_exact(nano_num), num_exact(nano_den));
5382 else if (submicro !=
Qnil) {
5390 if (10 <= (
digit =
ptr[0] >> 4))
goto end_submicro;
5391 nsec +=
digit * 100;
5392 if (10 <= (
digit =
ptr[0] & 0xf))
goto end_submicro;
5396 if (10 <= (
digit =
ptr[1] >> 4))
goto end_submicro;
5402 timew = timegmw(&vtm);
5408 tobj->timew = timew;
5413 time_set_utc_offset(time,
offset);
5418 tobj->vtm.zone =
zone;
5419 zone_localtime(
zone, time);
5433 VALUE time = time_s_alloc(klass);
5435 time_mload(time,
str);
5456 struct time_object *tobj;
5460 struct time_object *ttm;
5463 tm = time_s_alloc(klass);
5466 GMTIMEW(ttm->timew = tobj->timew, v);
5467 ttm->timew = wsub(ttm->timew, v->subsecx);
5482 GMTIMEW(tobj->timew, v = &vtm);
5483 args[i++] = v->year;
5490 case 0: args[i++] =
Qfalse;
break;
5491 case 1: args[i++] =
Qtrue;
break;
5492 default: args[i++] =
Qnil;
break;
5494 args[i++] = w2v(rb_time_unmagnify(tobj->timew));
5518 struct time_object *tobj =
DATA_PTR(tm);
5547 struct time_object *torig = get_timeval(tm);
5549 struct time_object *tobj =
DATA_PTR(dup);
5554 const VALUE *p = RSTRUCT_CONST_PTR(tm);
5571#define tm_subsec tm_zero
5572#define tm_utc_offset tm_zero
5583 const VALUE *p = RSTRUCT_CONST_PTR(tm);
5588 p[5], p[4], p[3], p[2], p[1], p[0]);
5644 "sec",
"min",
"hour",
5645 "mday",
"mon",
"year",
5656 rb_alias(tm, rb_intern_const(
"to_time"), rb_intern_const(
"utc"));
5666 VALUE tm, abbr, strftime_args[2];
5669 if (!
NIL_P(abbr))
return abbr;
5671 tm = tm_from_time(rb_cTimeTM, time);
5676#ifdef SUPPORT_TZINFO_ZONE_ABBREVIATION
5684 strftime_args[1] = tm;
5830 id_submicro = rb_intern_const(
"submicro");
5831 id_nano_num = rb_intern_const(
"nano_num");
5832 id_nano_den = rb_intern_const(
"nano_den");
5833 id_offset = rb_intern_const(
"offset");
5834 id_zone = rb_intern_const(
"zone");
5835 id_nanosecond = rb_intern_const(
"nanosecond");
5836 id_microsecond = rb_intern_const(
"microsecond");
5837 id_millisecond = rb_intern_const(
"millisecond");
5838 id_nsec = rb_intern_const(
"nsec");
5839 id_usec = rb_intern_const(
"usec");
5840 id_local_to_utc = rb_intern_const(
"local_to_utc");
5841 id_utc_to_local = rb_intern_const(
"utc_to_local");
5842 id_year = rb_intern_const(
"year");
5843 id_mon = rb_intern_const(
"mon");
5844 id_mday = rb_intern_const(
"mday");
5845 id_hour = rb_intern_const(
"hour");
5846 id_min = rb_intern_const(
"min");
5847 id_sec = rb_intern_const(
"sec");
5848 id_isdst = rb_intern_const(
"isdst");
5849 id_find_timezone = rb_intern_const(
"find_timezone");
5942#ifdef DEBUG_FIND_TIME_NUMGUESS
5946 rb_cTimeTM = Init_tm(
rb_cTime,
"tm");
VALUE rb_check_array_type(VALUE ary)
VALUE rb_ary_entry(VALUE ary, long offset)
#define PACKED_STRUCT_UNALIGNED(x)
#define UNREACHABLE_RETURN
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
VALUE rb_big_minus(VALUE x, VALUE y)
VALUE rb_big_modulo(VALUE x, VALUE y)
VALUE rb_big_plus(VALUE x, VALUE y)
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
size_t rb_absint_size(VALUE val, int *nlz_bits_ret)
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
VALUE rb_big_cmp(VALUE x, VALUE y)
VALUE rb_big_mul(VALUE x, VALUE y)
VALUE rb_big_div(VALUE x, VALUE y)
int bits(struct state *s, int need)
VALUE rb_invcmp(VALUE x, VALUE y)
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
VALUE rb_int_positive_pow(long x, unsigned long y)
rb_encoding * rb_enc_get(VALUE obj)
rb_encoding * rb_locale_encoding(void)
rb_encoding * rb_usascii_encoding(void)
#define rb_cmpint(cmp, a, b)
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
void rb_gc_mark(VALUE ptr)
void rb_gc_register_mark_object(VALUE obj)
Inform the garbage collector that object is a live Ruby object that should not be moved.
void rb_include_module(VALUE klass, VALUE module)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
VALUE rb_exc_new_str(VALUE etype, VALUE str)
VALUE rb_rescue(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2)
An equivalent of rescue clause.
void rb_sys_fail(const char *mesg)
void rb_warning(const char *fmt,...)
VALUE rb_Float(VALUE)
Equivalent to Kernel#Float in Ruby.
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
VALUE rb_cObject
Object class.
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
VALUE rb_obj_class(VALUE)
VALUE rb_equal(VALUE, VALUE)
This function is an optimized version of calling #==.
VALUE rb_to_int(VALUE)
Converts val into Integer.
#define rb_enc_str_asciicompat_p(str)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Thin wrapper to ruby/config.h.
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
#define INTEGER_PACK_NATIVE_BYTE_ORDER
#define INTEGER_PACK_LITTLE_ENDIAN
void rb_num_zerodiv(void)
#define OBJ_INIT_COPY(obj, orig)
VALUE rb_rational_new(VALUE, VALUE)
VALUE rb_str_resize(VALUE, long)
VALUE rb_str_concat(VALUE, VALUE)
#define rb_str_new(str, len)
#define rb_usascii_str_new(str, len)
VALUE rb_check_string_type(VALUE)
#define rb_usascii_str_new_cstr(str)
VALUE rb_obj_as_string(VALUE)
#define rb_str_cat_cstr(buf, str)
VALUE rb_usascii_str_new_static(const char *ptr, long len)
VALUE rb_struct_define_under(VALUE, const char *,...)
void rb_copy_generic_ivar(VALUE, VALUE)
VALUE rb_ivar_set(VALUE, ID, VALUE)
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
int rb_respond_to(VALUE, ID)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void rb_alias(VALUE, ID, ID)
ID rb_intern(const char *)
Internal header for Array.
Internal header for Comparable.
Internal header for Numeric.
int rb_int_positive_p(VALUE num)
VALUE rb_int_minus(VALUE x, VALUE y)
VALUE rb_int_plus(VALUE x, VALUE y)
Internal header for Rational.
VALUE rb_rational_canonicalize(VALUE x)
VALUE rb_numeric_quo(VALUE x, VALUE y)
Internal header for String.
#define rb_fstring_lit(str)
VALUE rb_str_tmp_frozen_acquire(VALUE str)
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Internal header for Time.
VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE)
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
Internal header for Math.
#define MEMCPY(p1, p2, type, n)
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
#define StringValuePtr(v)
#define StringValueCStr(v)
#define RUBY_TYPED_DEFAULT_FREE
#define TypedData_Get_Struct(obj, type, data_type, sval)
@ RUBY_TYPED_FREE_IMMEDIATELY
#define TypedData_Make_Struct(klass, type, data_type, sval)
#define RB_INTEGER_TYPE_P(obj)
unsigned long long uint64_t
VALUE rb_str_catf(VALUE, const char *,...)
VALUE rb_sprintf(const char *,...)
size_t strlen(const char *)
VALUE rb_strftime_timespec(const char *format, size_t format_len, rb_encoding *enc, VALUE time, const struct vtm *vtm, struct timespec *ts, int gmt)
VALUE rb_strftime(const char *format, size_t format_len, rb_encoding *enc, VALUE time, const struct vtm *vtm, VALUE timev, int gmt)
#define MUL_OVERFLOW_FIXWV_P(a, b)
int ruby_marshal_write_long(long x, char *buf)
#define GMTIME(tm, result)
#define wmulquoll(x, y, z)
#define validate_vtm_range(mem, b, e)
#define TZMODE_SET_LOCALTIME(tobj)
#define TIME_TZMODE_UNINITIALIZED
VALUE rb_time_nano_new(time_t sec, long nsec)
#define TZMODE_UTC_P(tobj)
long ruby_marshal_read_long(const char **buf, long len)
#define TZMODE_COPY(tobj1, tobj2)
void rb_timespec_now(struct timespec *ts)
void ruby_reset_leap_second_info(void)
VALUE rb_time_zone_abbreviation(VALUE zone, VALUE time)
SIGNED_VALUE SIGNED_WIDEVALUE
#define GetTimeval(obj, tobj)
#define DEBUG_REPORT_GUESSRANGE
VALUE rb_time_timespec_new(const struct timespec *ts, int offset)
Returns a time object with UTC/localtime/fixed offset.
struct timespec rb_time_timespec(VALUE time)
#define arg_range_check(v)
#define TIME_TZMODE_LOCALTIME
#define LOCALTIME(tm, result)
#define strftimev(fmt, time, enc)
#define MAKE_TM_ENSURE(time, tobj, cond)
void ruby_reset_timezone(void)
#define TZMODE_SET_UTC(tobj)
VALUE rb_time_new(time_t sec, long usec)
struct timeval rb_time_timeval(VALUE time)
struct timeval rb_time_interval(VALUE num)
VALUE rb_time_num_new(VALUE timev, VALUE off)
#define TZMODE_LOCALTIME_P(tobj)
#define TZMODE_FIXOFF_P(tobj)
#define GetNewTimeval(obj, tobj)
VALUE rb_time_utc_offset(VALUE time)
#define TZMODE_SET_FIXOFF(tobj, off)
struct timespec rb_time_timespec_interval(VALUE num)
#define TIME_INIT_P(tobj)
#define get_attr(attr, iffound)
#define VTM_ISDST_INITVAL
#define MAKE_TM(time, tobj)
#define TYPEOF_TIMEVAL_TV_USEC
#define TYPEOF_TIMEVAL_TV_SEC
void error(const char *msg)
int gettimeofday(struct timeval *, struct timezone *)
struct tm * localtime_r(const time_t *, struct tm *)
int clock_gettime(clockid_t, struct timespec *)
struct tm * gmtime_r(const time_t *, struct tm *)