From 8dc69cf216b265859732ba4600cdc4d1fb1c65d1 Mon Sep 17 00:00:00 2001 From: Yukihiro Matsumoto Date: Mon, 23 Jul 2012 07:33:18 +0900 Subject: time.c: separate sec and usec to keep precisions --- src/time.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/time.c b/src/time.c index 94b76c8f9..f3072b7d9 100644 --- a/src/time.c +++ b/src/time.c @@ -160,13 +160,17 @@ mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm) /* Allocates a mrb_time object and initializes it. */ static struct mrb_time* -mrb_time_alloc(mrb_state *mrb, mrb_float seconds, enum mrb_timezone timezone) +mrb_time_alloc(mrb_state *mrb, mrb_float sec, mrb_float usec, enum mrb_timezone timezone) { struct mrb_time *tm; tm = mrb_malloc(mrb, sizeof(struct mrb_time)); - tm->sec = (time_t)seconds; - tm->usec = (seconds - tm->sec) * 1.0e6; + tm->sec = (time_t)sec; + tm->usec = (sec - tm->sec) * 1.0e6 + usec; + if (tm->usec < 0) { + tm->sec--; + tm->usec += 1.0e6; + } tm->timezone = timezone; mrb_time_update_datetime(tm); @@ -174,9 +178,9 @@ mrb_time_alloc(mrb_state *mrb, mrb_float seconds, enum mrb_timezone timezone) } static mrb_value -mrb_time_make(mrb_state *mrb, struct RClass *c, mrb_float seconds, enum mrb_timezone timezone) +mrb_time_make(mrb_state *mrb, struct RClass *c, mrb_float sec, mrb_float usec, enum mrb_timezone timezone) { - return mrb_time_wrap(mrb, c, mrb_time_alloc(mrb, seconds, timezone)); + return mrb_time_wrap(mrb, c, mrb_time_alloc(mrb, sec, usec, timezone)); } static struct mrb_time* @@ -230,8 +234,7 @@ mrb_time_at(mrb_state *mrb, mrb_value self) mrb_float f, f2 = 0; mrb_get_args(mrb, "f|f", &f, &f2); - f += f2 * 1e-6; - return mrb_time_make(mrb, mrb_class_ptr(self), f, MRB_TIMEZONE_LOCAL); + return mrb_time_make(mrb, mrb_class_ptr(self), f, f2, MRB_TIMEZONE_LOCAL); } static struct mrb_time* @@ -259,7 +262,7 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday, mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time."); } - return mrb_time_alloc(mrb, nowsecs+ausec/10e6, timezone); + return mrb_time_alloc(mrb, nowsecs, ausec, timezone); } /* 15.2.19.6.2 */ @@ -343,7 +346,7 @@ mrb_time_plus(mrb_state *mrb, mrb_value self) if (!tm) return mrb_nil_value(); f += tm->sec; f += (mrb_float)tm->usec / 1.0e6; - return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone); + return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, 0, tm->timezone); } static mrb_value @@ -364,11 +367,10 @@ mrb_time_minus(mrb_state *mrb, mrb_value self) return mrb_float_value(f); } else { - mrb_float f, f2; - mrb_get_args(mrb, "f", &f2); + mrb_float f; - f = ((mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6); - return mrb_time_make(mrb, mrb_obj_class(mrb, self), f-f2, tm->timezone); + mrb_get_args(mrb, "f", &f); + return mrb_time_make(mrb, mrb_obj_class(mrb, self), tm->sec-f, tm->usec, tm->timezone); } } -- cgit v1.2.3