@@ -95,17 +95,24 @@ def __new__(
9595 )
9696
9797 # Intuitive normalization
98- total = self .total_seconds () - (years * 365 + months * 30 ) * SECONDS_PER_DAY
98+ # Use exact integer microseconds to avoid total_seconds() float precision loss.
99+ total_microseconds = (
100+ (timedelta .days .__get__ (self ) - (years * 365 + months * 30 ))
101+ * SECONDS_PER_DAY
102+ + timedelta .seconds .__get__ (self )
103+ ) * US_PER_SECOND + timedelta .microseconds .__get__ (self )
104+ total = total_microseconds / US_PER_SECOND
99105 self ._total = total
100106
101107 m = 1
102- if total < 0 :
108+ if total_microseconds < 0 :
103109 m = - 1
104110
105- self ._microseconds = round (total % m * 1e6 )
106- self ._seconds = abs (int (total )) % SECONDS_PER_DAY * m
111+ abs_microseconds = abs (total_microseconds )
112+ self ._microseconds = abs_microseconds % US_PER_SECOND * m
113+ self ._seconds = abs_microseconds // US_PER_SECOND % SECONDS_PER_DAY * m
107114
108- _days = abs ( int ( total )) // SECONDS_PER_DAY * m
115+ _days = abs_microseconds // US_PER_SECOND // SECONDS_PER_DAY * m
109116 self ._days = _days
110117 self ._remaining_days = abs (_days ) % 7 * m
111118 self ._weeks = abs (_days ) // 7 * m
@@ -509,11 +516,15 @@ def __new__(
509516 )
510517
511518 # Intuitive normalization
512- self ._total = delta .total_seconds ()
513- total = abs (self ._total )
514-
515- self ._microseconds = round (total % 1 * 1e6 )
516- days , self ._seconds = divmod (int (total ), SECONDS_PER_DAY )
519+ # Use exact integer microseconds to avoid total_seconds() float precision loss.
520+ total_microseconds = (
521+ delta .days * SECONDS_PER_DAY + delta .seconds
522+ ) * US_PER_SECOND + delta .microseconds
523+ self ._total = total_microseconds / US_PER_SECOND
524+ abs_microseconds = abs (total_microseconds )
525+
526+ self ._microseconds = abs_microseconds % US_PER_SECOND
527+ days , self ._seconds = divmod (abs_microseconds // US_PER_SECOND , SECONDS_PER_DAY )
517528 self ._days = abs (days + years * 365 + months * 30 )
518529 self ._weeks , self ._remaining_days = divmod (days , 7 )
519530 self ._months = abs (months )
0 commit comments