@@ -249,6 +249,7 @@ divmodv(VALUE n, VALUE d, VALUE *q, VALUE *r)
249249# define FIXWV2WINT (w ) FIX2LONG(WIDEVAL_GET(w))
250250#endif
251251
252+ #define SIZEOF_WIDEINT SIZEOF_INT64_T
252253#define POSFIXWVABLE (wi ) ((wi) < FIXWV_MAX+1)
253254#define NEGFIXWVABLE (wi ) ((wi) >= FIXWV_MIN)
254255#define FIXWV_P (w ) FIXWINT_P(WIDEVAL_GET(w))
@@ -1968,11 +1969,11 @@ time_modify(VALUE time)
19681969}
19691970
19701971static wideval_t
1971- timenano2timew (time_t sec , long nsec )
1972+ timenano2timew (wideint_t sec , long nsec )
19721973{
19731974 wideval_t timew ;
19741975
1975- timew = rb_time_magnify (TIMET2WV (sec ));
1976+ timew = rb_time_magnify (WINT2WV (sec ));
19761977 if (nsec )
19771978 timew = wadd (timew , wmulquoll (WINT2WV (nsec ), TIME_SCALE , 1000000000 ));
19781979 return timew ;
@@ -2747,46 +2748,35 @@ time_init_parse(rb_execution_context_t *ec, VALUE time, VALUE str, VALUE zone, V
27472748}
27482749
27492750static void
2750- subsec_normalize (time_t * secp , long * subsecp , const long maxsubsec )
2751+ subsec_normalize (wideint_t * secp , long * subsecp , const long maxsubsec )
27512752{
2752- time_t sec = * secp ;
2753+ wideint_t sec = * secp ;
27532754 long subsec = * subsecp ;
27542755 long sec2 ;
27552756
27562757 if (UNLIKELY (subsec >= maxsubsec )) { /* subsec positive overflow */
27572758 sec2 = subsec / maxsubsec ;
2758- if (TIMET_MAX - sec2 < sec ) {
2759+ if (WIDEINT_MAX - sec2 < sec ) {
27592760 rb_raise (rb_eRangeError , "out of Time range" );
27602761 }
27612762 subsec -= sec2 * maxsubsec ;
27622763 sec += sec2 ;
27632764 }
27642765 else if (UNLIKELY (subsec < 0 )) { /* subsec negative overflow */
27652766 sec2 = NDIV (subsec , maxsubsec ); /* negative div */
2766- if (sec < TIMET_MIN - sec2 ) {
2767+ if (sec < WIDEINT_MIN - sec2 ) {
27672768 rb_raise (rb_eRangeError , "out of Time range" );
27682769 }
27692770 subsec -= sec2 * maxsubsec ;
27702771 sec += sec2 ;
27712772 }
2772- #ifndef NEGATIVE_TIME_T
2773- if (sec < 0 )
2774- rb_raise (rb_eArgError , "time must be positive" );
2775- #endif
27762773 * secp = sec ;
27772774 * subsecp = subsec ;
27782775}
27792776
27802777#define time_usec_normalize (secp , usecp ) subsec_normalize(secp, usecp, 1000000)
27812778#define time_nsec_normalize (secp , nsecp ) subsec_normalize(secp, nsecp, 1000000000)
27822779
2783- static wideval_t
2784- nsec2timew (time_t sec , long nsec )
2785- {
2786- time_nsec_normalize (& sec , & nsec );
2787- return timenano2timew (sec , nsec );
2788- }
2789-
27902780static VALUE
27912781time_new_timew (VALUE klass , wideval_t timew )
27922782{
@@ -2800,25 +2790,39 @@ time_new_timew(VALUE klass, wideval_t timew)
28002790 return time ;
28012791}
28022792
2793+ static wideint_t
2794+ TIMETtoWIDEINT (time_t t )
2795+ {
2796+ #if SIZEOF_TIME_T * CHAR_BIT - (SIGNEDNESS_OF_TIME_T < 0 ) > \
2797+ SIZEOF_WIDEINT * CHAR_BIT - 1
2798+ /* compare in bit size without sign bit */
2799+ if (t > WIDEINT_MAX ) rb_raise (rb_eArgError , "out of Time range" );
2800+ #endif
2801+ return (wideint_t )t ;
2802+ }
2803+
28032804VALUE
28042805rb_time_new (time_t sec , long usec )
28052806{
2806- time_usec_normalize (& sec , & usec );
2807- return time_new_timew (rb_cTime , timenano2timew (sec , usec * 1000 ));
2807+ wideint_t isec = TIMETtoWIDEINT (sec );
2808+ time_usec_normalize (& isec , & usec );
2809+ return time_new_timew (rb_cTime , timenano2timew (isec , usec * 1000 ));
28082810}
28092811
28102812/* returns localtime time object */
28112813VALUE
28122814rb_time_nano_new (time_t sec , long nsec )
28132815{
2814- return time_new_timew (rb_cTime , nsec2timew (sec , nsec ));
2816+ wideint_t isec = TIMETtoWIDEINT (sec );
2817+ time_nsec_normalize (& isec , & nsec );
2818+ return time_new_timew (rb_cTime , timenano2timew (isec , nsec ));
28152819}
28162820
28172821VALUE
28182822rb_time_timespec_new (const struct timespec * ts , int offset )
28192823{
28202824 struct time_object * tobj ;
2821- VALUE time = time_new_timew ( rb_cTime , nsec2timew ( ts -> tv_sec , ts -> tv_nsec ) );
2825+ VALUE time = rb_time_nano_new ( ts -> tv_sec , ts -> tv_nsec );
28222826
28232827 if (-86400 < offset && offset < 86400 ) { /* fixoff */
28242828 GetTimeval (time , tobj );
0 commit comments