1
0
Fork 0
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:
akr 2009-08-29 19:06:29 +00:00
parent 4a9bca2496
commit 8b32a1de29
3 changed files with 177 additions and 146 deletions

View file

@ -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
View file

@ -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;
}

View file

@ -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