diff -r 7c6e3358221a Lib/datetime.py --- a/Lib/datetime.py Thu Feb 26 15:27:57 2015 +0200 +++ b/Lib/datetime.py Thu Feb 26 11:13:46 2015 -0500 @@ -297,6 +297,23 @@ raise TypeError("can't compare '%s' to '%s'" % ( type(x).__name__, type(y).__name__)) +def _divide_and_round(a, b): + """divide a by b and round result to the nearest integer + + When the ratio is exactly half-way between two integers, + the even integer is returned. + """ + if b < 0: + return -_divide_and_round(a, -b) + q, r = divmod(a, b) + r2 = r * 2 + if r2 > b: + return q + 1 + if r2 < b: + return q + # resolve ties to even + return q + (q & 1) + class timedelta: """Represent the difference between two datetime objects. @@ -515,8 +532,9 @@ self._seconds * other, self._microseconds * other) if isinstance(other, float): + usec = self._to_microseconds() a, b = other.as_integer_ratio() - return self * a / b + return timedelta(0, 0, _divide_and_round(usec * a, b)) return NotImplemented __rmul__ = __mul__ @@ -541,10 +559,10 @@ if isinstance(other, timedelta): return usec / other._to_microseconds() if isinstance(other, int): - return timedelta(0, 0, usec / other) + return timedelta(0, 0, _divide_and_round(usec, other)) if isinstance(other, float): a, b = other.as_integer_ratio() - return timedelta(0, 0, b * usec / a) + return timedelta(0, 0, _divide_and_round(b * usec, a)) def __mod__(self, other): if isinstance(other, timedelta): diff -r 7c6e3358221a Lib/test/datetimetester.py --- a/Lib/test/datetimetester.py Thu Feb 26 15:27:57 2015 +0200 +++ b/Lib/test/datetimetester.py Thu Feb 26 11:13:46 2015 -0500 @@ -62,6 +62,17 @@ 'tzinfo']) self.assertEqual(names - allowed, set([])) + def test_divide_and_round(self): + if '_Fast' in str(self): + return + dar = datetime_module._divide_and_round + self.assertEqual(dar(-10, -3), 3) + self.assertEqual(dar(5, -2), -2) + # ties to even + self.assertEqual(dar(10, -4), -2) + self.assertEqual(dar(-10, 4), -2) + self.assertEqual(dar(-10, -4), 2) + ############################################################################# # tzinfo tests @@ -394,6 +405,10 @@ eq((-3*us) * 0.5, -2*us) eq((-5*us) * 0.5, -2*us) + # Issue #23521 + eq(td(seconds=1) * 0.123456, td(microseconds=123456)) + eq(td(seconds=1) * 0.6112295, td(microseconds=611229)) + # Division by int and float eq((3*us) / 2, 2*us) eq((5*us) / 2, 2*us) @@ -408,6 +423,9 @@ for i in range(-10, 10): eq((i*us/-3)//us, round(i/-3)) + # Issue #23521 + eq(td(seconds=1) / (1 / 0.6112295), td(microseconds=611229)) + # Issue #11576 eq(td(999999999, 86399, 999999) - td(999999999, 86399, 999998), td(0, 0, 1))