static void num2timespec(struct timespec *ts, VALUE t) { switch (TYPE(t)) { case T_FIXNUM: case T_BIGNUM: ts->tv_sec = NUM2TIMET(t); ts->tv_nsec = 0; break; case T_FLOAT: { double f, d; double val = RFLOAT_VALUE(t); d = modf(val, &f); if (d >= 0) { ts->tv_nsec = (long)(d * 1e9 + 0.5); } else { ts->tv_nsec = (long)(-d * 1e9 + 0.5); if (ts->tv_nsec > 0) { ts->tv_nsec = 1000000000 - ts->tv_nsec; f -= 1; } } ts->tv_sec = (time_t)f; if (f != ts->tv_sec) rb_raise(rb_eRangeError, "%f out of range", val); } break; default: { VALUE f; VALUE ary = rb_funcall(t, id_divmod, 1, INT2FIX(1)); Check_Type(ary, T_ARRAY); ts->tv_sec = NUM2TIMET(rb_ary_entry(ary, 0)); f = rb_ary_entry(ary, 1); f = rb_funcall(f, '*', 1, INT2FIX(1000000000)); ts->tv_nsec = NUM2LONG(f); } } }
static VALUE time_spec_rb_time_new(VALUE self, VALUE sec, VALUE usec) { return rb_time_new(NUM2TIMET(sec), NUM2LONG(usec)); }