summaryrefslogtreecommitdiff
path: root/time.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2021-04-01 12:00:10 +0900
committerGitHub <noreply@github.com>2021-04-01 12:00:10 +0900
commita5567350f706d6c72b2d4e0cdc95ceff80e87bbf (patch)
tree74d1341fb41ea14177ab0f16a3f87121813d83f8 /time.c
parent2a02b61fae2c5dcfaf123f43c08c7c7949c1790c (diff)
Refactored sub-seconds normalizations
* separated argument to `timespec2timew` from `timespec` to seconds and nano-seconds. * unified nano-seconds and micro-seconds normalizations.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4343 Merged-By: nobu <nobu@ruby-lang.org>
Diffstat (limited to 'time.c')
-rw-r--r--time.c61
1 files changed, 21 insertions, 40 deletions
diff --git a/time.c b/time.c
index bfcce8ee0f..e24bb5a012 100644
--- a/time.c
+++ b/time.c
@@ -1844,13 +1844,13 @@ time_modify(VALUE time)
}
static wideval_t
-timespec2timew(struct timespec *ts)
+timenano2timew(time_t sec, long nsec)
{
wideval_t timew;
- timew = rb_time_magnify(TIMET2WV(ts->tv_sec));
- if (ts->tv_nsec)
- timew = wadd(timew, wmulquoll(WINT2WV(ts->tv_nsec), TIME_SCALE, 1000000000));
+ timew = rb_time_magnify(TIMET2WV(sec));
+ if (nsec)
+ timew = wadd(timew, wmulquoll(WINT2WV(nsec), TIME_SCALE, 1000000000));
return timew;
}
@@ -1918,7 +1918,7 @@ time_init_now(rb_execution_context_t *ec, VALUE time, VALUE zone)
tobj->tm_got=0;
tobj->timew = WINT2FIXWV(0);
rb_timespec_now(&ts);
- tobj->timew = timespec2timew(&ts);
+ tobj->timew = timenano2timew(ts.tv_sec, ts.tv_nsec);
if (!NIL_P(zone)) {
time_zonelocal(time, zone);
@@ -2409,26 +2409,26 @@ time_init_args(rb_execution_context_t *ec, VALUE time, VALUE year, VALUE mon, VA
}
static void
-time_overflow_p(time_t *secp, long *nsecp)
+subsec_normalize(time_t *secp, long *subsecp, const long maxsubsec)
{
time_t sec = *secp;
- long nsec = *nsecp;
+ long subsec = *subsecp;
long sec2;
- if (nsec >= 1000000000) { /* nsec positive overflow */
- sec2 = nsec / 1000000000;
+ if (UNLIKELY(subsec >= maxsubsec)) { /* subsec positive overflow */
+ sec2 = subsec / maxsubsec;
if (TIMET_MAX - sec2 < sec) {
rb_raise(rb_eRangeError, "out of Time range");
}
- nsec -= sec2 * 1000000000;
+ subsec -= sec2 * maxsubsec;
sec += sec2;
}
- else if (nsec < 0) { /* nsec negative overflow */
- sec2 = NDIV(nsec,1000000000); /* negative div */
+ else if (UNLIKELY(subsec < 0)) { /* subsec negative overflow */
+ sec2 = NDIV(subsec, maxsubsec); /* negative div */
if (sec < TIMET_MIN - sec2) {
rb_raise(rb_eRangeError, "out of Time range");
}
- nsec -= sec2 * 1000000000;
+ subsec -= sec2 * maxsubsec;
sec += sec2;
}
#ifndef NEGATIVE_TIME_T
@@ -2436,17 +2436,17 @@ time_overflow_p(time_t *secp, long *nsecp)
rb_raise(rb_eArgError, "time must be positive");
#endif
*secp = sec;
- *nsecp = nsec;
+ *subsecp = subsec;
}
+#define time_usec_normalize(secp, usecp) subsec_normalize(secp, usecp, 1000000)
+#define time_nsec_normalize(secp, nsecp) subsec_normalize(secp, nsecp, 1000000000)
+
static wideval_t
nsec2timew(time_t sec, long nsec)
{
- struct timespec ts;
- time_overflow_p(&sec, &nsec);
- ts.tv_sec = sec;
- ts.tv_nsec = nsec;
- return timespec2timew(&ts);
+ time_nsec_normalize(&sec, &nsec);
+ return timenano2timew(sec, nsec);
}
static VALUE
@@ -2465,27 +2465,8 @@ time_new_timew(VALUE klass, wideval_t timew)
VALUE
rb_time_new(time_t sec, long usec)
{
- wideval_t timew;
-
- if (usec >= 1000000) {
- long sec2 = usec / 1000000;
- if (sec > TIMET_MAX - sec2) {
- rb_raise(rb_eRangeError, "out of Time range");
- }
- usec -= sec2 * 1000000;
- sec += sec2;
- }
- else if (usec < 0) {
- long sec2 = NDIV(usec,1000000); /* negative div */
- if (sec < TIMET_MIN - sec2) {
- rb_raise(rb_eRangeError, "out of Time range");
- }
- usec -= sec2 * 1000000;
- sec += sec2;
- }
-
- timew = nsec2timew(sec, usec * 1000);
- return time_new_timew(rb_cTime, timew);
+ time_usec_normalize(&sec, &usec);
+ return time_new_timew(rb_cTime, timenano2timew(sec, usec * 1000));
}
/* returns localtime time object */