mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
Normalize subseconds using wideint_t
instead of time_t
This commit is contained in:
parent
b8de3cfb04
commit
583ce06c0e
Notes:
git
2025-06-13 10:36:05 +00:00
1 changed files with 25 additions and 21 deletions
46
time.c
46
time.c
|
@ -249,6 +249,7 @@ divmodv(VALUE n, VALUE d, VALUE *q, VALUE *r)
|
||||||
# define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
|
# define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SIZEOF_WIDEINT SIZEOF_INT64_T
|
||||||
#define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
|
#define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
|
||||||
#define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
|
#define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
|
||||||
#define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
|
#define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
|
||||||
|
@ -1968,11 +1969,11 @@ time_modify(VALUE time)
|
||||||
}
|
}
|
||||||
|
|
||||||
static wideval_t
|
static wideval_t
|
||||||
timenano2timew(time_t sec, long nsec)
|
timenano2timew(wideint_t sec, long nsec)
|
||||||
{
|
{
|
||||||
wideval_t timew;
|
wideval_t timew;
|
||||||
|
|
||||||
timew = rb_time_magnify(TIMET2WV(sec));
|
timew = rb_time_magnify(WINT2WV(sec));
|
||||||
if (nsec)
|
if (nsec)
|
||||||
timew = wadd(timew, wmulquoll(WINT2WV(nsec), TIME_SCALE, 1000000000));
|
timew = wadd(timew, wmulquoll(WINT2WV(nsec), TIME_SCALE, 1000000000));
|
||||||
return timew;
|
return timew;
|
||||||
|
@ -2747,15 +2748,15 @@ only_year:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
subsec_normalize(time_t *secp, long *subsecp, const long maxsubsec)
|
subsec_normalize(wideint_t *secp, long *subsecp, const long maxsubsec)
|
||||||
{
|
{
|
||||||
time_t sec = *secp;
|
wideint_t sec = *secp;
|
||||||
long subsec = *subsecp;
|
long subsec = *subsecp;
|
||||||
long sec2;
|
long sec2;
|
||||||
|
|
||||||
if (UNLIKELY(subsec >= maxsubsec)) { /* subsec positive overflow */
|
if (UNLIKELY(subsec >= maxsubsec)) { /* subsec positive overflow */
|
||||||
sec2 = subsec / maxsubsec;
|
sec2 = subsec / maxsubsec;
|
||||||
if (TIMET_MAX - sec2 < sec) {
|
if (WIDEINT_MAX - sec2 < sec) {
|
||||||
rb_raise(rb_eRangeError, "out of Time range");
|
rb_raise(rb_eRangeError, "out of Time range");
|
||||||
}
|
}
|
||||||
subsec -= sec2 * maxsubsec;
|
subsec -= sec2 * maxsubsec;
|
||||||
|
@ -2763,16 +2764,12 @@ subsec_normalize(time_t *secp, long *subsecp, const long maxsubsec)
|
||||||
}
|
}
|
||||||
else if (UNLIKELY(subsec < 0)) { /* subsec negative overflow */
|
else if (UNLIKELY(subsec < 0)) { /* subsec negative overflow */
|
||||||
sec2 = NDIV(subsec, maxsubsec); /* negative div */
|
sec2 = NDIV(subsec, maxsubsec); /* negative div */
|
||||||
if (sec < TIMET_MIN - sec2) {
|
if (sec < WIDEINT_MIN - sec2) {
|
||||||
rb_raise(rb_eRangeError, "out of Time range");
|
rb_raise(rb_eRangeError, "out of Time range");
|
||||||
}
|
}
|
||||||
subsec -= sec2 * maxsubsec;
|
subsec -= sec2 * maxsubsec;
|
||||||
sec += sec2;
|
sec += sec2;
|
||||||
}
|
}
|
||||||
#ifndef NEGATIVE_TIME_T
|
|
||||||
if (sec < 0)
|
|
||||||
rb_raise(rb_eArgError, "time must be positive");
|
|
||||||
#endif
|
|
||||||
*secp = sec;
|
*secp = sec;
|
||||||
*subsecp = subsec;
|
*subsecp = subsec;
|
||||||
}
|
}
|
||||||
|
@ -2780,13 +2777,6 @@ subsec_normalize(time_t *secp, long *subsecp, const long maxsubsec)
|
||||||
#define time_usec_normalize(secp, usecp) subsec_normalize(secp, usecp, 1000000)
|
#define time_usec_normalize(secp, usecp) subsec_normalize(secp, usecp, 1000000)
|
||||||
#define time_nsec_normalize(secp, nsecp) subsec_normalize(secp, nsecp, 1000000000)
|
#define time_nsec_normalize(secp, nsecp) subsec_normalize(secp, nsecp, 1000000000)
|
||||||
|
|
||||||
static wideval_t
|
|
||||||
nsec2timew(time_t sec, long nsec)
|
|
||||||
{
|
|
||||||
time_nsec_normalize(&sec, &nsec);
|
|
||||||
return timenano2timew(sec, nsec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
time_new_timew(VALUE klass, wideval_t timew)
|
time_new_timew(VALUE klass, wideval_t timew)
|
||||||
{
|
{
|
||||||
|
@ -2800,25 +2790,39 @@ time_new_timew(VALUE klass, wideval_t timew)
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static wideint_t
|
||||||
|
TIMETtoWIDEINT(time_t t)
|
||||||
|
{
|
||||||
|
#if SIZEOF_TIME_T * CHAR_BIT - (SIGNEDNESS_OF_TIME_T < 0) > \
|
||||||
|
SIZEOF_WIDEINT * CHAR_BIT - 1
|
||||||
|
/* compare in bit size without sign bit */
|
||||||
|
if (t > WIDEINT_MAX) rb_raise(rb_eArgError, "out of Time range");
|
||||||
|
#endif
|
||||||
|
return (wideint_t)t;
|
||||||
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_time_new(time_t sec, long usec)
|
rb_time_new(time_t sec, long usec)
|
||||||
{
|
{
|
||||||
time_usec_normalize(&sec, &usec);
|
wideint_t isec = TIMETtoWIDEINT(sec);
|
||||||
return time_new_timew(rb_cTime, timenano2timew(sec, usec * 1000));
|
time_usec_normalize(&isec, &usec);
|
||||||
|
return time_new_timew(rb_cTime, timenano2timew(isec, usec * 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns localtime time object */
|
/* returns localtime time object */
|
||||||
VALUE
|
VALUE
|
||||||
rb_time_nano_new(time_t sec, long nsec)
|
rb_time_nano_new(time_t sec, long nsec)
|
||||||
{
|
{
|
||||||
return time_new_timew(rb_cTime, nsec2timew(sec, nsec));
|
wideint_t isec = TIMETtoWIDEINT(sec);
|
||||||
|
time_nsec_normalize(&isec, &nsec);
|
||||||
|
return time_new_timew(rb_cTime, timenano2timew(isec, nsec));
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_time_timespec_new(const struct timespec *ts, int offset)
|
rb_time_timespec_new(const struct timespec *ts, int offset)
|
||||||
{
|
{
|
||||||
struct time_object *tobj;
|
struct time_object *tobj;
|
||||||
VALUE time = time_new_timew(rb_cTime, nsec2timew(ts->tv_sec, ts->tv_nsec));
|
VALUE time = rb_time_nano_new(ts->tv_sec, ts->tv_nsec);
|
||||||
|
|
||||||
if (-86400 < offset && offset < 86400) { /* fixoff */
|
if (-86400 < offset && offset < 86400) { /* fixoff */
|
||||||
GetTimeval(time, tobj);
|
GetTimeval(time, tobj);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue