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))
|
||||
#endif
|
||||
|
||||
#define SIZEOF_WIDEINT SIZEOF_INT64_T
|
||||
#define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
|
||||
#define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
|
||||
#define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
|
||||
|
@ -1968,11 +1969,11 @@ time_modify(VALUE time)
|
|||
}
|
||||
|
||||
static wideval_t
|
||||
timenano2timew(time_t sec, long nsec)
|
||||
timenano2timew(wideint_t sec, long nsec)
|
||||
{
|
||||
wideval_t timew;
|
||||
|
||||
timew = rb_time_magnify(TIMET2WV(sec));
|
||||
timew = rb_time_magnify(WINT2WV(sec));
|
||||
if (nsec)
|
||||
timew = wadd(timew, wmulquoll(WINT2WV(nsec), TIME_SCALE, 1000000000));
|
||||
return timew;
|
||||
|
@ -2747,15 +2748,15 @@ only_year:
|
|||
}
|
||||
|
||||
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 sec2;
|
||||
|
||||
if (UNLIKELY(subsec >= maxsubsec)) { /* subsec positive overflow */
|
||||
sec2 = subsec / maxsubsec;
|
||||
if (TIMET_MAX - sec2 < sec) {
|
||||
if (WIDEINT_MAX - sec2 < sec) {
|
||||
rb_raise(rb_eRangeError, "out of Time range");
|
||||
}
|
||||
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 */
|
||||
sec2 = NDIV(subsec, maxsubsec); /* negative div */
|
||||
if (sec < TIMET_MIN - sec2) {
|
||||
if (sec < WIDEINT_MIN - sec2) {
|
||||
rb_raise(rb_eRangeError, "out of Time range");
|
||||
}
|
||||
subsec -= sec2 * maxsubsec;
|
||||
sec += sec2;
|
||||
}
|
||||
#ifndef NEGATIVE_TIME_T
|
||||
if (sec < 0)
|
||||
rb_raise(rb_eArgError, "time must be positive");
|
||||
#endif
|
||||
*secp = sec;
|
||||
*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_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
|
||||
time_new_timew(VALUE klass, wideval_t timew)
|
||||
{
|
||||
|
@ -2800,25 +2790,39 @@ time_new_timew(VALUE klass, wideval_t timew)
|
|||
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
|
||||
rb_time_new(time_t sec, long usec)
|
||||
{
|
||||
time_usec_normalize(&sec, &usec);
|
||||
return time_new_timew(rb_cTime, timenano2timew(sec, usec * 1000));
|
||||
wideint_t isec = TIMETtoWIDEINT(sec);
|
||||
time_usec_normalize(&isec, &usec);
|
||||
return time_new_timew(rb_cTime, timenano2timew(isec, usec * 1000));
|
||||
}
|
||||
|
||||
/* returns localtime time object */
|
||||
VALUE
|
||||
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
|
||||
rb_time_timespec_new(const struct timespec *ts, int offset)
|
||||
{
|
||||
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 */
|
||||
GetTimeval(time, tobj);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue