mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* timev.h (TIME_SCALE): defined as 1000000000.
(struct vtm): subsec is replaced by subsecx. subsec * TIME_SCALE == subsecx. * time.c: avoid rational in most cases. (struct time_object): timev is replaced by timexv. timev * TIME_SCALE == timexv. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24707 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4a9bca2496
commit
8b32a1de29
3 changed files with 177 additions and 146 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
Sun Aug 30 03:59:43 2009 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* timev.h (TIME_SCALE): defined as 1000000000.
|
||||
(struct vtm): subsec is replaced by subsecx.
|
||||
subsec * TIME_SCALE == subsecx.
|
||||
|
||||
* time.c: avoid rational in most cases.
|
||||
(struct time_object): timev is replaced by timexv.
|
||||
timev * TIME_SCALE == timexv.
|
||||
|
||||
Sun Aug 30 03:17:25 2009 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* time.c (init_leap_second_info): use TIMET_MAX.
|
||||
|
|
309
time.c
309
time.c
|
@ -66,7 +66,7 @@ static int tmcmp(struct tm *a, struct tm *b);
|
|||
static int vtmcmp(struct vtm *a, struct vtm *b);
|
||||
static const char *find_time_t(struct tm *tptr, int utc_p, time_t *tp);
|
||||
|
||||
static struct vtm *localtimev(VALUE timev, struct vtm *result);
|
||||
static struct vtm *localtimexv(VALUE timexv, struct vtm *result);
|
||||
|
||||
static int leap_year_p(long y);
|
||||
#define leap_year_v_p(y) leap_year_p(NUM2LONG(mod(v, INT2FIX(400))))
|
||||
|
@ -133,6 +133,8 @@ quo(VALUE x, VALUE y)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define mulquo(x,y,z) ((y == z) ? x : quo(mul(x,y),z))
|
||||
|
||||
static void
|
||||
divmodv(VALUE n, VALUE d, VALUE *q, VALUE *r)
|
||||
{
|
||||
|
@ -180,6 +182,18 @@ num_exact(VALUE v)
|
|||
return v;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_time_magnify(VALUE v)
|
||||
{
|
||||
return mul(v, INT2FIX(TIME_SCALE));
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_time_unmagnify(VALUE v)
|
||||
{
|
||||
return quo(v, INT2FIX(TIME_SCALE));
|
||||
}
|
||||
|
||||
static const int common_year_yday_offset[] = {
|
||||
-1,
|
||||
-1 + 31,
|
||||
|
@ -219,7 +233,7 @@ static const int leap_year_days_in_month[] = {
|
|||
};
|
||||
|
||||
static VALUE
|
||||
timegmv_noleapsecond(struct vtm *vtm)
|
||||
timegmxv_noleapsecond(struct vtm *vtm)
|
||||
{
|
||||
VALUE year1900;
|
||||
VALUE q400, r400;
|
||||
|
@ -255,7 +269,7 @@ timegmv_noleapsecond(struct vtm *vtm)
|
|||
ret = add(ret, mul(LONG2NUM(days_in400), INT2FIX(86400)));
|
||||
ret = add(ret, mul(q400, INT2FIX(97*86400)));
|
||||
ret = add(ret, mul(year1900, INT2FIX(365*86400)));
|
||||
ret = add(ret, vtm->subsec);
|
||||
ret = add(rb_time_magnify(ret), vtm->subsecx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -282,16 +296,17 @@ zone_str(const char *s)
|
|||
}
|
||||
|
||||
static void
|
||||
gmtimev_noleapsecond(VALUE timev, struct vtm *vtm)
|
||||
gmtimexv_noleapsecond(VALUE timexv, struct vtm *vtm)
|
||||
{
|
||||
VALUE v;
|
||||
int i, n, x, y;
|
||||
const int *yday_offset;
|
||||
int wday;
|
||||
VALUE timev;
|
||||
|
||||
vtm->isdst = 0;
|
||||
|
||||
divmodv(timev, INT2FIX(1), &timev, &vtm->subsec);
|
||||
divmodv(timexv, INT2FIX(TIME_SCALE), &timev, &vtm->subsecx);
|
||||
divmodv(timev, INT2FIX(86400), &timev, &v);
|
||||
|
||||
wday = NUM2INT(mod(timev, INT2FIX(7)));
|
||||
|
@ -521,7 +536,7 @@ init_leap_second_info()
|
|||
time_t now;
|
||||
struct tm *tm, result;
|
||||
struct vtm vtm;
|
||||
VALUE timev;
|
||||
VALUE timexv;
|
||||
now = time(NULL);
|
||||
gmtime(&now);
|
||||
tm = gmtime_with_leapsecond(&now, &result);
|
||||
|
@ -541,19 +556,19 @@ init_leap_second_info()
|
|||
vtm.hour = result.tm_hour;
|
||||
vtm.min = result.tm_min;
|
||||
vtm.sec = result.tm_sec;
|
||||
vtm.subsec = INT2FIX(0);
|
||||
vtm.subsecx = INT2FIX(0);
|
||||
vtm.utc_offset = INT2FIX(0);
|
||||
|
||||
timev = timegmv_noleapsecond(&vtm);
|
||||
timexv = timegmxv_noleapsecond(&vtm);
|
||||
|
||||
number_of_leap_seconds_known = NUM2INT(sub(TIMET2NUM(known_leap_seconds_limit), timev));
|
||||
number_of_leap_seconds_known = NUM2INT(sub(TIMET2NUM(known_leap_seconds_limit), rb_time_unmagnify(timexv)));
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
timegmv(struct vtm *vtm)
|
||||
timegmxv(struct vtm *vtm)
|
||||
{
|
||||
VALUE timev;
|
||||
VALUE timexv;
|
||||
struct tm tm;
|
||||
time_t t;
|
||||
const char *errmsg;
|
||||
|
@ -561,14 +576,14 @@ timegmv(struct vtm *vtm)
|
|||
/* The first leap second is 1972-06-30 23:59:60 UTC.
|
||||
* No leap seconds before. */
|
||||
if (RTEST(gt(INT2FIX(1972), vtm->year)))
|
||||
return timegmv_noleapsecond(vtm);
|
||||
return timegmxv_noleapsecond(vtm);
|
||||
|
||||
init_leap_second_info();
|
||||
|
||||
timev = timegmv_noleapsecond(vtm);
|
||||
timexv = timegmxv_noleapsecond(vtm);
|
||||
|
||||
if (RTEST(lt(TIMET2NUM(known_leap_seconds_limit), timev))) {
|
||||
return add(timev, INT2NUM(number_of_leap_seconds_known));
|
||||
if (RTEST(lt(rb_time_magnify(TIMET2NUM(known_leap_seconds_limit)), timexv))) {
|
||||
return add(timexv, rb_time_magnify(INT2NUM(number_of_leap_seconds_known)));
|
||||
}
|
||||
|
||||
tm.tm_year = NUM2LONG(vtm->year) - 1900;
|
||||
|
@ -582,30 +597,31 @@ timegmv(struct vtm *vtm)
|
|||
errmsg = find_time_t(&tm, 1, &t);
|
||||
if (errmsg)
|
||||
rb_raise(rb_eArgError, "%s", errmsg);
|
||||
return add(TIMET2NUM(t), vtm->subsec);
|
||||
return add(rb_time_magnify(TIMET2NUM(t)), vtm->subsecx);
|
||||
}
|
||||
|
||||
static struct vtm *
|
||||
gmtimev(VALUE timev, struct vtm *result)
|
||||
gmtimexv(VALUE timexv, struct vtm *result)
|
||||
{
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
VALUE subsec;
|
||||
VALUE subsecx;
|
||||
VALUE timev;
|
||||
|
||||
if (RTEST(lt(timev, INT2FIX(0)))) {
|
||||
gmtimev_noleapsecond(timev, result);
|
||||
if (RTEST(lt(timexv, INT2FIX(0)))) {
|
||||
gmtimexv_noleapsecond(timexv, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
init_leap_second_info();
|
||||
|
||||
if (RTEST(lt(LONG2NUM(known_leap_seconds_limit), timev))) {
|
||||
timev = sub(timev, INT2NUM(number_of_leap_seconds_known));
|
||||
gmtimev_noleapsecond(timev, result);
|
||||
if (RTEST(lt(rb_time_magnify(LONG2NUM(known_leap_seconds_limit)), timexv))) {
|
||||
timexv = sub(timexv, rb_time_magnify(INT2NUM(number_of_leap_seconds_known)));
|
||||
gmtimexv_noleapsecond(timexv, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
divmodv(timev, INT2FIX(1), &timev, &subsec);
|
||||
divmodv(timexv, INT2FIX(TIME_SCALE), &timev, &subsecx);
|
||||
|
||||
t = NUM2TIMET(timev);
|
||||
if (!gmtime_with_leapsecond(&t, &tm))
|
||||
|
@ -617,7 +633,7 @@ gmtimev(VALUE timev, struct vtm *result)
|
|||
result->hour = tm.tm_hour;
|
||||
result->min = tm.tm_min;
|
||||
result->sec = tm.tm_sec;
|
||||
result->subsec = subsec;
|
||||
result->subsecx = subsecx;
|
||||
result->utc_offset = INT2FIX(0);
|
||||
result->wday = tm.tm_wday;
|
||||
result->yday = tm.tm_yday+1;
|
||||
|
@ -760,7 +776,7 @@ guess_local_offset(struct vtm *vtm_utc)
|
|||
else
|
||||
vtm2.year = INT2FIX(compat_common_month_table[vtm_utc->mon-1][wday]);
|
||||
|
||||
timev = timegmv(&vtm2);
|
||||
timev = rb_time_unmagnify(timegmxv(&vtm2));
|
||||
t = NUM2TIMET(timev);
|
||||
if (localtime_with_gmtoff(&t, &tm, &gmtoff))
|
||||
return LONG2FIX(gmtoff);
|
||||
|
@ -796,12 +812,12 @@ small_vtm_sub(struct vtm *vtm1, struct vtm *vtm2)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
timelocalv(struct vtm *vtm)
|
||||
timelocalxv(struct vtm *vtm)
|
||||
{
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
VALUE v;
|
||||
VALUE timev1, timev2;
|
||||
VALUE timexv1, timexv2;
|
||||
struct vtm vtm1, vtm2;
|
||||
int n;
|
||||
|
||||
|
@ -827,54 +843,54 @@ timelocalv(struct vtm *vtm)
|
|||
|
||||
if (find_time_t(&tm, 0, &t))
|
||||
goto no_localtime;
|
||||
return add(TIMET2NUM(t), vtm->subsec);
|
||||
return add(rb_time_magnify(TIMET2NUM(t)), vtm->subsecx);
|
||||
|
||||
no_localtime:
|
||||
timev1 = timegmv(vtm);
|
||||
timexv1 = timegmxv(vtm);
|
||||
|
||||
if (!localtimev(timev1, &vtm1))
|
||||
rb_raise(rb_eArgError, "localtimev error");
|
||||
if (!localtimexv(timexv1, &vtm1))
|
||||
rb_raise(rb_eArgError, "localtimexv error");
|
||||
|
||||
n = vtmcmp(vtm, &vtm1);
|
||||
if (n == 0) {
|
||||
timev1 = sub(timev1, INT2FIX(12*3600));
|
||||
if (!localtimev(timev1, &vtm1))
|
||||
rb_raise(rb_eArgError, "localtimev error");
|
||||
timexv1 = sub(timexv1, rb_time_magnify(INT2FIX(12*3600)));
|
||||
if (!localtimexv(timexv1, &vtm1))
|
||||
rb_raise(rb_eArgError, "localtimexv error");
|
||||
n = 1;
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
timev2 = timev1;
|
||||
timexv2 = timexv1;
|
||||
vtm2 = vtm1;
|
||||
timev1 = sub(timev1, INT2FIX(24*3600));
|
||||
if (!localtimev(timev1, &vtm1))
|
||||
rb_raise(rb_eArgError, "localtimev error");
|
||||
timexv1 = sub(timexv1, rb_time_magnify(INT2FIX(24*3600)));
|
||||
if (!localtimexv(timexv1, &vtm1))
|
||||
rb_raise(rb_eArgError, "localtimexv error");
|
||||
}
|
||||
else {
|
||||
timev2 = add(timev1, INT2FIX(24*3600));
|
||||
if (!localtimev(timev2, &vtm2))
|
||||
rb_raise(rb_eArgError, "localtimev error");
|
||||
timexv2 = add(timexv1, rb_time_magnify(INT2FIX(24*3600)));
|
||||
if (!localtimexv(timexv2, &vtm2))
|
||||
rb_raise(rb_eArgError, "localtimexv error");
|
||||
}
|
||||
timev1 = add(timev1, small_vtm_sub(vtm, &vtm1));
|
||||
timev2 = add(timev2, small_vtm_sub(vtm, &vtm2));
|
||||
timexv1 = add(timexv1, rb_time_magnify(small_vtm_sub(vtm, &vtm1)));
|
||||
timexv2 = add(timexv2, rb_time_magnify(small_vtm_sub(vtm, &vtm2)));
|
||||
|
||||
if (eq(timev1, timev2))
|
||||
return timev1;
|
||||
if (eq(timexv1, timexv2))
|
||||
return timexv1;
|
||||
|
||||
if (!localtimev(timev1, &vtm1))
|
||||
rb_raise(rb_eArgError, "localtimev error");
|
||||
if (!localtimexv(timexv1, &vtm1))
|
||||
rb_raise(rb_eArgError, "localtimexv error");
|
||||
if (vtm->hour != vtm1.hour || vtm->min != vtm1.min || vtm->sec != vtm1.sec)
|
||||
return timev2;
|
||||
return timexv2;
|
||||
|
||||
if (!localtimev(timev2, &vtm2))
|
||||
rb_raise(rb_eArgError, "localtimev error");
|
||||
if (!localtimexv(timexv2, &vtm2))
|
||||
rb_raise(rb_eArgError, "localtimexv error");
|
||||
if (vtm->hour != vtm2.hour || vtm->min != vtm2.min || vtm->sec != vtm2.sec)
|
||||
return timev1;
|
||||
return timexv1;
|
||||
|
||||
if (vtm->isdst)
|
||||
return lt(vtm1.utc_offset, vtm2.utc_offset) ? timev2 : timev1;
|
||||
return lt(vtm1.utc_offset, vtm2.utc_offset) ? timexv2 : timexv1;
|
||||
else
|
||||
return lt(vtm1.utc_offset, vtm2.utc_offset) ? timev1 : timev2;
|
||||
return lt(vtm1.utc_offset, vtm2.utc_offset) ? timexv1 : timexv2;
|
||||
}
|
||||
|
||||
static struct tm *
|
||||
|
@ -913,10 +929,10 @@ localtime_with_gmtoff(const time_t *t, struct tm *result, long *gmtoff)
|
|||
}
|
||||
|
||||
static struct vtm *
|
||||
localtimev(VALUE timev, struct vtm *result)
|
||||
localtimexv(VALUE timexv, struct vtm *result)
|
||||
{
|
||||
VALUE subsec, offset;
|
||||
divmodv(timev, INT2FIX(1), &timev, &subsec);
|
||||
VALUE timev, subsecx, offset;
|
||||
divmodv(timexv, INT2FIX(TIME_SCALE), &timev, &subsecx);
|
||||
|
||||
if (le(TIMET2NUM(TIMET_MIN), timev) &&
|
||||
le(timev, TIMET2NUM(TIMET_MAX))) {
|
||||
|
@ -932,7 +948,7 @@ localtimev(VALUE timev, struct vtm *result)
|
|||
result->hour = tm.tm_hour;
|
||||
result->min = tm.tm_min;
|
||||
result->sec = tm.tm_sec;
|
||||
result->subsec = subsec;
|
||||
result->subsecx = subsecx;
|
||||
result->wday = tm.tm_wday;
|
||||
result->yday = tm.tm_yday+1;
|
||||
result->isdst = tm.tm_isdst;
|
||||
|
@ -954,12 +970,12 @@ localtimev(VALUE timev, struct vtm *result)
|
|||
}
|
||||
}
|
||||
|
||||
if (!gmtimev(timev, result))
|
||||
if (!gmtimexv(timexv, result))
|
||||
return NULL;
|
||||
|
||||
offset = guess_local_offset(result);
|
||||
|
||||
if (!gmtimev(add(timev, offset), result))
|
||||
if (!gmtimexv(add(timexv, rb_time_magnify(offset)), result))
|
||||
return NULL;
|
||||
|
||||
result->utc_offset = offset;
|
||||
|
@ -968,7 +984,7 @@ localtimev(VALUE timev, struct vtm *result)
|
|||
}
|
||||
|
||||
struct time_object {
|
||||
VALUE timev;
|
||||
VALUE timexv;
|
||||
struct vtm vtm;
|
||||
int gmt;
|
||||
int tm_got;
|
||||
|
@ -1004,9 +1020,9 @@ time_mark(void *ptr)
|
|||
{
|
||||
struct time_object *tobj = ptr;
|
||||
if (!tobj) return;
|
||||
rb_gc_mark(tobj->timev);
|
||||
rb_gc_mark(tobj->timexv);
|
||||
rb_gc_mark(tobj->vtm.year);
|
||||
rb_gc_mark(tobj->vtm.subsec);
|
||||
rb_gc_mark(tobj->vtm.subsecx);
|
||||
rb_gc_mark(tobj->vtm.utc_offset);
|
||||
}
|
||||
|
||||
|
@ -1024,7 +1040,7 @@ time_s_alloc(VALUE klass)
|
|||
|
||||
obj = Data_Make_Struct(klass, struct time_object, time_mark, time_free, tobj);
|
||||
tobj->tm_got=0;
|
||||
tobj->timev = INT2FIX(0);
|
||||
tobj->timexv = INT2FIX(0);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
@ -1038,27 +1054,27 @@ time_modify(VALUE time)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
timespec2timev(struct timespec *ts)
|
||||
timespec2timexv(struct timespec *ts)
|
||||
{
|
||||
VALUE timev;
|
||||
VALUE timexv;
|
||||
|
||||
timev = TIMET2NUM(ts->tv_sec);
|
||||
timexv = rb_time_magnify(TIMET2NUM(ts->tv_sec));
|
||||
if (ts->tv_nsec)
|
||||
timev = add(timev, quo(LONG2NUM(ts->tv_nsec), INT2FIX(1000000000)));
|
||||
return timev;
|
||||
timexv = add(timexv, mulquo(LONG2NUM(ts->tv_nsec), INT2FIX(TIME_SCALE), INT2FIX(1000000000)));
|
||||
return timexv;
|
||||
}
|
||||
|
||||
static struct timespec
|
||||
timev2timespec(VALUE timev)
|
||||
timexv2timespec(VALUE timexv)
|
||||
{
|
||||
VALUE subsec;
|
||||
VALUE timev, subsecx;
|
||||
struct timespec ts;
|
||||
|
||||
divmodv(timev, INT2FIX(1), &timev, &subsec);
|
||||
divmodv(timexv, INT2FIX(TIME_SCALE), &timev, &subsecx);
|
||||
if (lt(timev, TIMET2NUM(TIMET_MIN)) || lt(TIMET2NUM(TIMET_MAX), timev))
|
||||
rb_raise(rb_eArgError, "time out of system range");
|
||||
ts.tv_sec = NUM2TIMET(timev);
|
||||
ts.tv_nsec = NUM2LONG(mul(subsec, INT2FIX(1000000000)));
|
||||
ts.tv_nsec = NUM2LONG(mulquo(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE)));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
@ -1078,7 +1094,7 @@ time_init_0(VALUE time)
|
|||
time_modify(time);
|
||||
GetTimeval(time, tobj);
|
||||
tobj->tm_got=0;
|
||||
tobj->timev = INT2FIX(0);
|
||||
tobj->timexv = INT2FIX(0);
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
|
||||
rb_sys_fail("clock_gettime");
|
||||
|
@ -1093,7 +1109,7 @@ time_init_0(VALUE time)
|
|||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
}
|
||||
#endif
|
||||
tobj->timev = timespec2timev(&ts);
|
||||
tobj->timexv = timespec2timexv(&ts);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
@ -1148,13 +1164,13 @@ vtm_add_offset(struct vtm *vtm, VALUE off)
|
|||
day = 0;
|
||||
|
||||
if (!rb_equal(subsec, INT2FIX(0))) {
|
||||
vtm->subsec = add(vtm->subsec, subsec);
|
||||
if (lt(vtm->subsec, INT2FIX(0))) {
|
||||
vtm->subsec = add(vtm->subsec, INT2FIX(1));
|
||||
vtm->subsecx = add(vtm->subsecx, rb_time_magnify(subsec));
|
||||
if (lt(vtm->subsecx, INT2FIX(0))) {
|
||||
vtm->subsecx = add(vtm->subsecx, INT2FIX(TIME_SCALE));
|
||||
sec -= 1;
|
||||
}
|
||||
if (le(INT2FIX(1), vtm->subsec)) {
|
||||
vtm->subsec = sub(vtm->subsec, INT2FIX(1));
|
||||
if (le(INT2FIX(TIME_SCALE), vtm->subsecx)) {
|
||||
vtm->subsecx = sub(vtm->subsecx, INT2FIX(TIME_SCALE));
|
||||
sec += 1;
|
||||
}
|
||||
goto not_zero_sec;
|
||||
|
@ -1293,13 +1309,13 @@ time_init_1(int argc, VALUE *argv, VALUE time)
|
|||
vtm.min = NIL_P(v[4]) ? 0 : obj2long(v[4]);
|
||||
|
||||
vtm.sec = 0;
|
||||
vtm.subsec = INT2FIX(0);
|
||||
vtm.subsecx = INT2FIX(0);
|
||||
if (!NIL_P(v[5])) {
|
||||
VALUE sec = num_exact(v[5]);
|
||||
VALUE subsec;
|
||||
divmodv(sec, INT2FIX(1), &sec, &subsec);
|
||||
vtm.sec = NUM2INT(sec);
|
||||
vtm.subsec = subsec;
|
||||
vtm.subsecx = rb_time_magnify(subsec);
|
||||
}
|
||||
|
||||
vtm.isdst = -1;
|
||||
|
@ -1319,17 +1335,17 @@ time_init_1(int argc, VALUE *argv, VALUE time)
|
|||
time_modify(time);
|
||||
GetTimeval(time, tobj);
|
||||
tobj->tm_got=0;
|
||||
tobj->timev = INT2FIX(0);
|
||||
tobj->timexv = INT2FIX(0);
|
||||
|
||||
if (!NIL_P(vtm.utc_offset)) {
|
||||
VALUE off = vtm.utc_offset;
|
||||
vtm_add_offset(&vtm, neg(off));
|
||||
vtm.utc_offset = Qnil;
|
||||
tobj->timev = timegmv(&vtm);
|
||||
tobj->timexv = timegmxv(&vtm);
|
||||
return time_set_utc_offset(time, off);
|
||||
}
|
||||
else {
|
||||
tobj->timev = timelocalv(&vtm);
|
||||
tobj->timexv = timelocalxv(&vtm);
|
||||
return time_localtime(time);
|
||||
}
|
||||
}
|
||||
|
@ -1409,23 +1425,23 @@ time_overflow_p(time_t *secp, long *nsecp)
|
|||
*nsecp = nsec;
|
||||
}
|
||||
|
||||
static VALUE nsec2timev(time_t sec, long nsec)
|
||||
static VALUE nsec2timexv(time_t sec, long nsec)
|
||||
{
|
||||
struct timespec ts;
|
||||
time_overflow_p(&sec, &nsec);
|
||||
ts.tv_sec = sec;
|
||||
ts.tv_nsec = nsec;
|
||||
return timespec2timev(&ts);
|
||||
return timespec2timexv(&ts);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
time_new_internal(VALUE klass, VALUE timev)
|
||||
time_new_internal(VALUE klass, VALUE timexv)
|
||||
{
|
||||
VALUE time = time_s_alloc(klass);
|
||||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
tobj->timev = num_exact(timev);
|
||||
tobj->timexv = num_exact(timexv);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
@ -1433,19 +1449,19 @@ time_new_internal(VALUE klass, VALUE timev)
|
|||
VALUE
|
||||
rb_time_new(time_t sec, long usec)
|
||||
{
|
||||
return time_new_internal(rb_cTime, nsec2timev(sec, usec * 1000));
|
||||
return time_new_internal(rb_cTime, nsec2timexv(sec, usec * 1000));
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_time_nano_new(time_t sec, long nsec)
|
||||
{
|
||||
return time_new_internal(rb_cTime, nsec2timev(sec, nsec));
|
||||
return time_new_internal(rb_cTime, nsec2timexv(sec, nsec));
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_time_num_new(VALUE timev, VALUE off)
|
||||
{
|
||||
VALUE time = time_new_internal(rb_cTime, timev);
|
||||
VALUE time = time_new_internal(rb_cTime, rb_time_magnify(timev));
|
||||
|
||||
if (!NIL_P(off)) {
|
||||
off = utc_offset_arg(off);
|
||||
|
@ -1458,13 +1474,13 @@ rb_time_num_new(VALUE timev, VALUE off)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
time_new_timev(VALUE klass, VALUE timev)
|
||||
time_new_timexv(VALUE klass, VALUE timexv)
|
||||
{
|
||||
VALUE time = time_s_alloc(klass);
|
||||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
tobj->timev = timev;
|
||||
tobj->timexv = timexv;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
@ -1568,7 +1584,7 @@ rb_time_timeval(VALUE time)
|
|||
|
||||
if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
|
||||
GetTimeval(time, tobj);
|
||||
ts = timev2timespec(tobj->timev);
|
||||
ts = timexv2timespec(tobj->timexv);
|
||||
t.tv_sec = (TYPEOF_TIMEVAL_TV_SEC)ts.tv_sec;
|
||||
t.tv_usec = (TYPEOF_TIMEVAL_TV_USEC)(ts.tv_nsec / 1000);
|
||||
return t;
|
||||
|
@ -1584,7 +1600,7 @@ rb_time_timespec(VALUE time)
|
|||
|
||||
if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
|
||||
GetTimeval(time, tobj);
|
||||
t = timev2timespec(tobj->timev);
|
||||
t = timexv2timespec(tobj->timexv);
|
||||
return t;
|
||||
}
|
||||
return time_timespec(time, Qfalse);
|
||||
|
@ -1629,24 +1645,24 @@ time_s_now(VALUE klass)
|
|||
static VALUE
|
||||
time_s_at(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
VALUE time, t, timev;
|
||||
VALUE time, t, timexv;
|
||||
|
||||
if (rb_scan_args(argc, argv, "11", &time, &t) == 2) {
|
||||
time = num_exact(time);
|
||||
t = num_exact(t);
|
||||
timev = add(time, quo(t, INT2FIX(1000000)));
|
||||
t = time_new_timev(klass, timev);
|
||||
timexv = add(rb_time_magnify(time), mulquo(t, INT2FIX(TIME_SCALE), INT2FIX(1000000)));
|
||||
t = time_new_timexv(klass, timexv);
|
||||
}
|
||||
else if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
|
||||
struct time_object *tobj, *tobj2;
|
||||
GetTimeval(time, tobj);
|
||||
t = time_new_timev(klass, tobj->timev);
|
||||
t = time_new_timexv(klass, tobj->timexv);
|
||||
GetTimeval(t, tobj2);
|
||||
TIME_COPY_GMT(tobj2, tobj);
|
||||
}
|
||||
else {
|
||||
timev = num_exact(time);
|
||||
t = time_new_timev(klass, timev);
|
||||
timexv = rb_time_magnify(num_exact(time));
|
||||
t = time_new_timexv(klass, timexv);
|
||||
}
|
||||
|
||||
return t;
|
||||
|
@ -1681,26 +1697,29 @@ obj2vint(VALUE obj)
|
|||
}
|
||||
|
||||
static long
|
||||
obj2subsec(VALUE obj, VALUE *subsec)
|
||||
obj2subsecx(VALUE obj, VALUE *subsecx)
|
||||
{
|
||||
VALUE subsec;
|
||||
|
||||
if (TYPE(obj) == T_STRING) {
|
||||
obj = rb_str_to_inum(obj, 10, Qfalse);
|
||||
*subsec = INT2FIX(0);
|
||||
*subsecx = INT2FIX(0);
|
||||
return NUM2LONG(obj);
|
||||
}
|
||||
|
||||
divmodv(num_exact(obj), INT2FIX(1), &obj, subsec);
|
||||
divmodv(num_exact(obj), INT2FIX(1), &obj, &subsec);
|
||||
*subsecx = rb_time_magnify(subsec);
|
||||
return NUM2LONG(obj);
|
||||
}
|
||||
|
||||
static long
|
||||
usec2subsec(VALUE obj)
|
||||
usec2subsecx(VALUE obj)
|
||||
{
|
||||
if (TYPE(obj) == T_STRING) {
|
||||
obj = rb_str_to_inum(obj, 10, Qfalse);
|
||||
}
|
||||
|
||||
return quo(num_exact(obj), INT2FIX(1000000));
|
||||
return mulquo(num_exact(obj), INT2FIX(TIME_SCALE), INT2FIX(1000000));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1748,7 +1767,7 @@ validate_vtm(struct vtm *vtm)
|
|||
|| (vtm->hour == 24 && (vtm->min > 0 || vtm->sec > 0))
|
||||
|| vtm->min < 0 || vtm->min > 59
|
||||
|| vtm->sec < 0 || vtm->sec > 60
|
||||
|| lt(vtm->subsec, INT2FIX(0)) || ge(vtm->subsec, INT2FIX(1))
|
||||
|| lt(vtm->subsecx, INT2FIX(0)) || ge(vtm->subsecx, INT2FIX(TIME_SCALE))
|
||||
|| (!NIL_P(vtm->utc_offset) && (validate_utc_offset(vtm->utc_offset), 0)))
|
||||
rb_raise(rb_eArgError, "argument out of range");
|
||||
}
|
||||
|
@ -1764,7 +1783,7 @@ time_arg(int argc, VALUE *argv, struct vtm *vtm)
|
|||
vtm->hour = 0;
|
||||
vtm->min = 0;
|
||||
vtm->sec = 0;
|
||||
vtm->subsec = INT2FIX(0);
|
||||
vtm->subsecx = INT2FIX(0);
|
||||
vtm->utc_offset = Qnil;
|
||||
vtm->wday = 0;
|
||||
vtm->yday = 0;
|
||||
|
@ -1811,11 +1830,11 @@ time_arg(int argc, VALUE *argv, struct vtm *vtm)
|
|||
|
||||
if (!NIL_P(v[6]) && argc == 7) {
|
||||
vtm->sec = NIL_P(v[5])?0:obj2long(v[5]);
|
||||
vtm->subsec = usec2subsec(v[6]);
|
||||
vtm->subsecx = usec2subsecx(v[6]);
|
||||
}
|
||||
else {
|
||||
/* when argc == 8, v[6] is timezone, but ignored */
|
||||
vtm->sec = NIL_P(v[5])?0:obj2subsec(v[5], &vtm->subsec);
|
||||
vtm->sec = NIL_P(v[5])?0:obj2subsecx(v[5], &vtm->subsecx);
|
||||
}
|
||||
|
||||
validate_vtm(vtm);
|
||||
|
@ -2139,8 +2158,8 @@ vtmcmp(struct vtm *a, struct vtm *b)
|
|||
return a->min < b->min ? -1 : 1;
|
||||
else if (a->sec != b->sec)
|
||||
return a->sec < b->sec ? -1 : 1;
|
||||
else if (ne(a->subsec, b->subsec))
|
||||
return lt(a->subsec, b->subsec) ? -1 : 1;
|
||||
else if (ne(a->subsecx, b->subsecx))
|
||||
return lt(a->subsecx, b->subsecx) ? -1 : 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -2172,9 +2191,9 @@ time_utc_or_local(int argc, VALUE *argv, int utc_p, VALUE klass)
|
|||
|
||||
time_arg(argc, argv, &vtm);
|
||||
if (utc_p)
|
||||
time = time_new_timev(klass, timegmv(&vtm));
|
||||
time = time_new_timexv(klass, timegmxv(&vtm));
|
||||
else
|
||||
time = time_new_timev(klass, timelocalv(&vtm));
|
||||
time = time_new_timexv(klass, timelocalxv(&vtm));
|
||||
if (utc_p) return time_gmtime(time);
|
||||
return time_localtime(time);
|
||||
}
|
||||
|
@ -2267,7 +2286,7 @@ time_to_i(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return div(tobj->timev, INT2FIX(1));
|
||||
return div(tobj->timexv, INT2FIX(TIME_SCALE));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2291,7 +2310,7 @@ time_to_f(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return rb_Float(tobj->timev);
|
||||
return rb_Float(rb_time_unmagnify(tobj->timexv));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2315,7 +2334,7 @@ time_to_r(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return tobj->timev;
|
||||
return rb_time_unmagnify(tobj->timexv);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2336,7 +2355,7 @@ time_usec(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return rb_to_int(mul(mod(tobj->timev, INT2FIX(1)), INT2FIX(1000000)));
|
||||
return rb_to_int(mulquo(mod(tobj->timexv, INT2FIX(TIME_SCALE)), INT2FIX(1000000), INT2FIX(TIME_SCALE)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2362,7 +2381,7 @@ time_nsec(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return rb_to_int(mul(mod(tobj->timev, INT2FIX(1)), INT2FIX(1000000000)));
|
||||
return rb_to_int(mulquo(mod(tobj->timexv, INT2FIX(TIME_SCALE)), INT2FIX(1000000000), INT2FIX(TIME_SCALE)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2389,7 +2408,7 @@ time_subsec(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return mod(tobj->timev, INT2FIX(1));
|
||||
return quo(mod(tobj->timexv, INT2FIX(TIME_SCALE)), INT2FIX(TIME_SCALE));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2421,7 +2440,7 @@ time_cmp(VALUE time1, VALUE time2)
|
|||
GetTimeval(time1, tobj1);
|
||||
if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) {
|
||||
GetTimeval(time2, tobj2);
|
||||
n = rb_cmpint(cmp(tobj1->timev, tobj2->timev), tobj1->timev, tobj2->timev);
|
||||
n = rb_cmpint(cmp(tobj1->timexv, tobj2->timexv), tobj1->timexv, tobj2->timexv);
|
||||
}
|
||||
else {
|
||||
VALUE cmp;
|
||||
|
@ -2453,7 +2472,7 @@ time_eql(VALUE time1, VALUE time2)
|
|||
GetTimeval(time1, tobj1);
|
||||
if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) {
|
||||
GetTimeval(time2, tobj2);
|
||||
return rb_equal(tobj1->timev, tobj2->timev);
|
||||
return rb_equal(tobj1->timexv, tobj2->timexv);
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
|
@ -2500,7 +2519,7 @@ time_hash(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return rb_hash(tobj->timev);
|
||||
return rb_hash(tobj->timexv);
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
|
@ -2544,7 +2563,7 @@ time_localtime(VALUE time)
|
|||
time_modify(time);
|
||||
}
|
||||
|
||||
if (!localtimev(tobj->timev, &vtm))
|
||||
if (!localtimexv(tobj->timexv, &vtm))
|
||||
rb_raise(rb_eArgError, "localtime error");
|
||||
tobj->vtm = vtm;
|
||||
|
||||
|
@ -2623,7 +2642,7 @@ time_gmtime(VALUE time)
|
|||
time_modify(time);
|
||||
}
|
||||
|
||||
if (!gmtimev(tobj->timev, &vtm))
|
||||
if (!gmtimexv(tobj->timexv, &vtm))
|
||||
rb_raise(rb_eArgError, "gmtime error");
|
||||
tobj->vtm = vtm;
|
||||
|
||||
|
@ -2653,7 +2672,7 @@ time_fixoff(VALUE time)
|
|||
else
|
||||
off = INT2FIX(0);
|
||||
|
||||
if (!gmtimev(tobj->timev, &vtm))
|
||||
if (!gmtimexv(tobj->timexv, &vtm))
|
||||
rb_raise(rb_eArgError, "gmtime error");
|
||||
|
||||
tobj->vtm = vtm;
|
||||
|
@ -2788,9 +2807,9 @@ time_add(struct time_object *tobj, VALUE offset, int sign)
|
|||
VALUE result;
|
||||
offset = num_exact(offset);
|
||||
if (sign < 0)
|
||||
result = time_new_timev(rb_cTime, sub(tobj->timev, offset));
|
||||
result = time_new_timexv(rb_cTime, sub(tobj->timexv, rb_time_magnify(offset)));
|
||||
else
|
||||
result = time_new_timev(rb_cTime, add(tobj->timev, offset));
|
||||
result = time_new_timexv(rb_cTime, add(tobj->timexv, rb_time_magnify(offset)));
|
||||
if (TIME_UTC_P(tobj)) {
|
||||
GetTimeval(result, tobj);
|
||||
TIME_SET_UTC(tobj);
|
||||
|
@ -2846,7 +2865,7 @@ time_minus(VALUE time1, VALUE time2)
|
|||
struct time_object *tobj2;
|
||||
|
||||
GetTimeval(time2, tobj2);
|
||||
return rb_Float(sub(tobj->timev, tobj2->timev));
|
||||
return rb_Float(rb_time_unmagnify(sub(tobj->timexv, tobj2->timexv)));
|
||||
}
|
||||
return time_add(tobj, time2, -1);
|
||||
}
|
||||
|
@ -2868,7 +2887,7 @@ time_succ(VALUE time)
|
|||
struct time_object *tobj2;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
time = time_new_timev(rb_cTime, add(tobj->timev, INT2FIX(1)));
|
||||
time = time_new_timexv(rb_cTime, add(tobj->timexv, INT2FIX(TIME_SCALE)));
|
||||
GetTimeval(time, tobj2);
|
||||
TIME_COPY_GMT(tobj2, tobj);
|
||||
return time;
|
||||
|
@ -3351,7 +3370,7 @@ strftimev(const char *fmt, VALUE time)
|
|||
|
||||
GetTimeval(time, tobj);
|
||||
MAKE_TM(time, tobj);
|
||||
len = rb_strftime_alloc(&buf, fmt, &tobj->vtm, tobj->timev, TIME_UTC_P(tobj));
|
||||
len = rb_strftime_alloc(&buf, fmt, &tobj->vtm, rb_time_unmagnify(tobj->timexv), TIME_UTC_P(tobj));
|
||||
str = rb_str_new(buf, len);
|
||||
if (buf != buffer) xfree(buf);
|
||||
return str;
|
||||
|
@ -3449,7 +3468,7 @@ time_strftime(VALUE time, VALUE format)
|
|||
|
||||
str = rb_str_new(0, 0);
|
||||
while (p < pe) {
|
||||
len = rb_strftime_alloc(&buf, p, &tobj->vtm, tobj->timev, TIME_UTC_P(tobj));
|
||||
len = rb_strftime_alloc(&buf, p, &tobj->vtm, rb_time_unmagnify(tobj->timexv), TIME_UTC_P(tobj));
|
||||
rb_str_cat(str, buf, len);
|
||||
p += strlen(p);
|
||||
if (buf != buffer) {
|
||||
|
@ -3463,7 +3482,7 @@ time_strftime(VALUE time, VALUE format)
|
|||
}
|
||||
else {
|
||||
len = rb_strftime_alloc(&buf, RSTRING_PTR(format),
|
||||
&tobj->vtm, tobj->timev, TIME_UTC_P(tobj));
|
||||
&tobj->vtm, rb_time_unmagnify(tobj->timexv), TIME_UTC_P(tobj));
|
||||
}
|
||||
str = rb_str_new(buf, len);
|
||||
if (buf != buffer) xfree(buf);
|
||||
|
@ -3487,11 +3506,11 @@ time_mdump(VALUE time)
|
|||
struct vtm vtm;
|
||||
long year;
|
||||
long usec, nsec;
|
||||
VALUE subsec, subnano, v;
|
||||
VALUE subsecx, nano, subnano, v;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
|
||||
gmtimev(tobj->timev, &vtm);
|
||||
gmtimexv(tobj->timexv, &vtm);
|
||||
|
||||
if (FIXNUM_P(vtm.year)) {
|
||||
year = FIX2LONG(vtm.year);
|
||||
|
@ -3502,10 +3521,10 @@ time_mdump(VALUE time)
|
|||
rb_raise(rb_eArgError, "year too big to marshal");
|
||||
}
|
||||
|
||||
subsec = vtm.subsec;
|
||||
subsecx = vtm.subsecx;
|
||||
|
||||
subsec = mul(subsec, INT2FIX(1000000000));
|
||||
divmodv(subsec, INT2FIX(1), &v, &subnano);
|
||||
nano = mulquo(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE));
|
||||
divmodv(nano, INT2FIX(1), &v, &subnano);
|
||||
nsec = FIX2LONG(v);
|
||||
usec = nsec / 1000;
|
||||
nsec = nsec % 1000;
|
||||
|
@ -3589,7 +3608,7 @@ time_mload(VALUE time, VALUE str)
|
|||
struct vtm vtm;
|
||||
int i, gmt;
|
||||
long nsec;
|
||||
VALUE timev, submicro, subnano;
|
||||
VALUE timexv, submicro, subnano;
|
||||
|
||||
time_modify(time);
|
||||
|
||||
|
@ -3622,7 +3641,7 @@ time_mload(VALUE time, VALUE str)
|
|||
sec = p;
|
||||
usec = s;
|
||||
nsec = usec * 1000;
|
||||
timev = add(TIMET2NUM(sec), quo(LONG2FIX(usec), LONG2FIX(1000000)));
|
||||
timexv = add(rb_time_magnify(TIMET2NUM(sec)), mulquo(LONG2FIX(usec), INT2FIX(TIME_SCALE), LONG2FIX(1000000)));
|
||||
}
|
||||
else {
|
||||
p &= ~(1UL<<31);
|
||||
|
@ -3661,18 +3680,18 @@ time_mload(VALUE time, VALUE str)
|
|||
end_submicro: ;
|
||||
}
|
||||
|
||||
vtm.subsec = quo(LONG2FIX(nsec), LONG2FIX(1000000000));
|
||||
vtm.subsecx = mulquo(LONG2FIX(nsec), INT2FIX(TIME_SCALE), LONG2FIX(1000000000));
|
||||
if (subnano != Qnil) {
|
||||
subnano = num_exact(subnano);
|
||||
vtm.subsec = add(vtm.subsec, quo(subnano, LONG2FIX(1000000000)));
|
||||
vtm.subsecx = add(vtm.subsecx, mulquo(subnano, INT2FIX(TIME_SCALE), LONG2FIX(1000000000)));
|
||||
}
|
||||
timev = timegmv(&vtm);
|
||||
timexv = timegmxv(&vtm);
|
||||
}
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
tobj->tm_got = 0;
|
||||
if (gmt) TIME_SET_UTC(tobj);
|
||||
tobj->timev = timev;
|
||||
tobj->timexv = timexv;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
|
4
timev.h
4
timev.h
|
@ -8,7 +8,7 @@ struct vtm {
|
|||
int hour; /* 0..23 */
|
||||
int min; /* 0..59 */
|
||||
int sec; /* 0..60 */
|
||||
VALUE subsec; /* 0 <= subsec < 1. possibly Rational. */
|
||||
VALUE subsecx; /* 0 <= subsecx < TIME_SCALE. possibly Rational. */
|
||||
VALUE utc_offset; /* -3600 as -01:00 for example. possibly Rational. */
|
||||
int wday; /* 0:Sunday, 1:Monday, ..., 6:Saturday */
|
||||
int yday; /* 1..366 */
|
||||
|
@ -16,4 +16,6 @@ struct vtm {
|
|||
const char *zone; /* "JST", "EST", "EDT", etc. */
|
||||
};
|
||||
|
||||
#define TIME_SCALE 1000000000
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue