Issue #23517: fromtimestamp() and utcfromtimestamp() methods of
datetime.datetime now round microseconds to nearest with ties going to nearest
even integer (ROUND_HALF_EVEN), as round(float), instead of rounding towards
-Infinity (ROUND_FLOOR).

pytime API: replace _PyTime_ROUND_HALF_UP with _PyTime_ROUND_HALF_EVEN. Fix
also _PyTime_Divide() for negative numbers.

_PyTime_AsTimeval_impl() now reuses _PyTime_Divide() instead of reimplementing
rounding modes.
diff --git a/Lib/datetime.py b/Lib/datetime.py
index 3c25ef8..3f29bc4 100644
--- a/Lib/datetime.py
+++ b/Lib/datetime.py
@@ -1380,7 +1380,7 @@
         A timezone info object may be passed in as well.
         """
         frac, t = _math.modf(t)
-        us = _round_half_up(frac * 1e6)
+        us = round(frac * 1e6)
         if us >= 1000000:
             t += 1
             us -= 1000000
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index d87b106..467fbe2 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -1874,7 +1874,7 @@
                 self.assertEqual(t, zero)
                 t = fts(-1/2**7)
                 self.assertEqual(t.second, 59)
-                self.assertEqual(t.microsecond, 992187)
+                self.assertEqual(t.microsecond, 992188)
 
             t = fts(1e-7)
             self.assertEqual(t, zero)
@@ -1888,7 +1888,7 @@
             self.assertEqual(t.microsecond, 0)
             t = fts(1/2**7)
             self.assertEqual(t.second, 0)
-            self.assertEqual(t.microsecond, 7813)
+            self.assertEqual(t.microsecond, 7812)
 
     def test_insane_fromtimestamp(self):
         # It's possible that some platform maps time_t to double,
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index d68dc4f..493b197 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -30,11 +30,11 @@
     ROUND_FLOOR = 0
     # Round towards infinity (+inf)
     ROUND_CEILING = 1
-    # Round to nearest with ties going away from zero
-    ROUND_HALF_UP = 2
+    # Round to nearest with ties going to nearest even integer
+    ROUND_HALF_EVEN = 2
 
 ALL_ROUNDING_METHODS = (_PyTime.ROUND_FLOOR, _PyTime.ROUND_CEILING,
-                        _PyTime.ROUND_HALF_UP)
+                        _PyTime.ROUND_HALF_EVEN)
 
 
 class TimeTestCase(unittest.TestCase):
@@ -639,27 +639,26 @@
         # Conversion giving different results depending on the rounding method
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP =  _PyTime.ROUND_HALF_UP
-        for obj, time_t, rnd in (
+        HALF_EVEN =  _PyTime.ROUND_HALF_EVEN
+        for obj, seconds, rnd in (
             (-1.9, -2, FLOOR),
             (-1.9, -1, CEILING),
-            (-1.9, -2, HALF_UP),
+            (-1.9, -2, HALF_EVEN),
 
             (1.9, 1, FLOOR),
             (1.9, 2, CEILING),
-            (1.9, 2, HALF_UP),
+            (1.9, 2, HALF_EVEN),
 
-            # half up
-            (-0.999, -1, HALF_UP),
-            (-0.510, -1, HALF_UP),
-            (-0.500, -1, HALF_UP),
-            (-0.490, 0, HALF_UP),
-            ( 0.490, 0, HALF_UP),
-            ( 0.500, 1, HALF_UP),
-            ( 0.510, 1, HALF_UP),
-            ( 0.999, 1, HALF_UP),
+            # half even
+            (-1.5, -2, HALF_EVEN),
+            (-0.9, -1, HALF_EVEN),
+            (-0.5,  0, HALF_EVEN),
+            ( 0.5,  0, HALF_EVEN),
+            ( 0.9,  1, HALF_EVEN),
+            ( 1.5,  2, HALF_EVEN),
         ):
-            self.assertEqual(pytime_object_to_time_t(obj, rnd), time_t)
+            with self.subTest(obj=obj, round=rnd, seconds=seconds):
+                self.assertEqual(pytime_object_to_time_t(obj, rnd), seconds)
 
         # Test OverflowError
         rnd = _PyTime.ROUND_FLOOR
@@ -691,15 +690,15 @@
         # Conversion giving different results depending on the rounding method
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP =  _PyTime.ROUND_HALF_UP
+        HALF_EVEN =  _PyTime.ROUND_HALF_EVEN
         for obj, timespec, rnd in (
             # Round towards minus infinity (-inf)
             (-1e-10, (0, 0), CEILING),
             (-1e-10, (-1, 999999999), FLOOR),
-            (-1e-10, (0, 0), HALF_UP),
+            (-1e-10, (0, 0), HALF_EVEN),
             (1e-10, (0, 0), FLOOR),
             (1e-10, (0, 1), CEILING),
-            (1e-10, (0, 0), HALF_UP),
+            (1e-10, (0, 0), HALF_EVEN),
 
             (0.9999999999, (0, 999999999), FLOOR),
             (0.9999999999, (1, 0), CEILING),
@@ -714,15 +713,13 @@
             (-1.1234567890, (-2, 876543211), CEILING),
             (-1.1234567891, (-2, 876543211), CEILING),
 
-            # half up
-            (-0.6e-9, (-1, 999999999), HALF_UP),
-            # skipped, 0.5e-6 is inexact in base 2
-            #(-0.5e-9, (-1, 999999999), HALF_UP),
-            (-0.4e-9, (0, 0), HALF_UP),
-
-            (0.4e-9, (0, 0), HALF_UP),
-            (0.5e-9, (0, 1), HALF_UP),
-            (0.6e-9, (0, 1), HALF_UP),
+            # half even
+            (-1.5e-9, (-1, 999999998), HALF_EVEN),
+            (-0.9e-9, (-1, 999999999), HALF_EVEN),
+            (-0.5e-9, (0, 0), HALF_EVEN),
+            (0.5e-9, (0, 0), HALF_EVEN),
+            (0.9e-9, (0, 1), HALF_EVEN),
+            (1.5e-9, (0, 2), HALF_EVEN),
         ):
             with self.subTest(obj=obj, round=rnd, timespec=timespec):
                 self.assertEqual(pytime_object_to_timespec(obj, rnd), timespec)
@@ -823,10 +820,10 @@
                 (-7.0, -7 * SEC_TO_NS),
 
                 # nanosecond are kept for value <= 2^23 seconds,
-                # except 2**23-1e-9 with HALF_UP
                 (2**22 - 1e-9,  4194303999999999),
                 (2**22,         4194304000000000),
                 (2**22 + 1e-9,  4194304000000001),
+                (2**23 - 1e-9,  8388607999999999),
                 (2**23,         8388608000000000),
 
                 # start loosing precision for value > 2^23 seconds
@@ -859,38 +856,31 @@
         # Conversion giving different results depending on the rounding method
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP =  _PyTime.ROUND_HALF_UP
+        HALF_EVEN =  _PyTime.ROUND_HALF_EVEN
         for obj, ts, rnd in (
             # close to zero
             ( 1e-10,  0, FLOOR),
             ( 1e-10,  1, CEILING),
-            ( 1e-10,  0, HALF_UP),
+            ( 1e-10,  0, HALF_EVEN),
             (-1e-10, -1, FLOOR),
             (-1e-10,  0, CEILING),
-            (-1e-10,  0, HALF_UP),
+            (-1e-10,  0, HALF_EVEN),
 
             # test rounding of the last nanosecond
             ( 1.1234567899,  1123456789, FLOOR),
             ( 1.1234567899,  1123456790, CEILING),
-            ( 1.1234567899,  1123456790, HALF_UP),
+            ( 1.1234567899,  1123456790, HALF_EVEN),
             (-1.1234567899, -1123456790, FLOOR),
             (-1.1234567899, -1123456789, CEILING),
-            (-1.1234567899, -1123456790, HALF_UP),
+            (-1.1234567899, -1123456790, HALF_EVEN),
 
             # close to 1 second
             ( 0.9999999999,   999999999, FLOOR),
             ( 0.9999999999,  1000000000, CEILING),
-            ( 0.9999999999,  1000000000, HALF_UP),
+            ( 0.9999999999,  1000000000, HALF_EVEN),
             (-0.9999999999, -1000000000, FLOOR),
             (-0.9999999999,  -999999999, CEILING),
-            (-0.9999999999, -1000000000, HALF_UP),
-
-            # close to 2^23 seconds
-            (2**23 - 1e-9,  8388607999999999, FLOOR),
-            (2**23 - 1e-9,  8388607999999999, CEILING),
-            # Issue #23517: skip HALF_UP test because the result is different
-            # depending on the FPU and how the compiler optimize the code :-/
-            #(2**23 - 1e-9,  8388608000000000, HALF_UP),
+            (-0.9999999999, -1000000000, HALF_EVEN),
         ):
             with self.subTest(obj=obj, round=rnd, timestamp=ts):
                 self.assertEqual(PyTime_FromSecondsObject(obj, rnd), ts)
@@ -958,33 +948,23 @@
 
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP = _PyTime.ROUND_HALF_UP
+        HALF_EVEN = _PyTime.ROUND_HALF_EVEN
         for ns, tv, rnd in (
             # nanoseconds
             (1, (0, 0), FLOOR),
             (1, (0, 1), CEILING),
-            (1, (0, 0), HALF_UP),
+            (1, (0, 0), HALF_EVEN),
             (-1, (-1, 999999), FLOOR),
             (-1, (0, 0), CEILING),
-            (-1, (0, 0), HALF_UP),
+            (-1, (0, 0), HALF_EVEN),
 
-            # seconds + nanoseconds
-            (1234567001, (1, 234567), FLOOR),
-            (1234567001, (1, 234568), CEILING),
-            (1234567001, (1, 234567), HALF_UP),
-            (-1234567001, (-2, 765432), FLOOR),
-            (-1234567001, (-2, 765433), CEILING),
-            (-1234567001, (-2, 765433), HALF_UP),
-
-            # half up
-            (499, (0, 0), HALF_UP),
-            (500, (0, 1), HALF_UP),
-            (501, (0, 1), HALF_UP),
-            (999, (0, 1), HALF_UP),
-            (-499, (0, 0), HALF_UP),
-            (-500, (0, 0), HALF_UP),
-            (-501, (-1, 999999), HALF_UP),
-            (-999, (-1, 999999), HALF_UP),
+            # half even
+            (-1500, (-1, 999998), HALF_EVEN),
+            (-999, (-1, 999999), HALF_EVEN),
+            (-500, (0, 0), HALF_EVEN),
+            (500, (0, 0), HALF_EVEN),
+            (999, (0, 1), HALF_EVEN),
+            (1500, (0, 2), HALF_EVEN),
         ):
             with self.subTest(nanoseconds=ns, timeval=tv, round=rnd):
                 self.assertEqual(PyTime_AsTimeval(ns, rnd), tv)
@@ -1027,33 +1007,31 @@
 
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP = _PyTime.ROUND_HALF_UP
+        HALF_EVEN = _PyTime.ROUND_HALF_EVEN
         for ns, ms, rnd in (
             # nanoseconds
             (1, 0, FLOOR),
             (1, 1, CEILING),
-            (1, 0, HALF_UP),
-            (-1, 0, FLOOR),
-            (-1, -1, CEILING),
-            (-1, 0, HALF_UP),
+            (1, 0, HALF_EVEN),
+            (-1, -1, FLOOR),
+            (-1, 0, CEILING),
+            (-1, 0, HALF_EVEN),
 
             # seconds + nanoseconds
             (1234 * MS_TO_NS + 1, 1234, FLOOR),
             (1234 * MS_TO_NS + 1, 1235, CEILING),
-            (1234 * MS_TO_NS + 1, 1234, HALF_UP),
-            (-1234 * MS_TO_NS - 1, -1234, FLOOR),
-            (-1234 * MS_TO_NS - 1, -1235, CEILING),
-            (-1234 * MS_TO_NS - 1, -1234, HALF_UP),
+            (1234 * MS_TO_NS + 1, 1234, HALF_EVEN),
+            (-1234 * MS_TO_NS - 1, -1235, FLOOR),
+            (-1234 * MS_TO_NS - 1, -1234, CEILING),
+            (-1234 * MS_TO_NS - 1, -1234, HALF_EVEN),
 
             # half up
-            (499999, 0, HALF_UP),
-            (499999, 0, HALF_UP),
-            (500000, 1, HALF_UP),
-            (999999, 1, HALF_UP),
-            (-499999, 0, HALF_UP),
-            (-500000, -1, HALF_UP),
-            (-500001, -1, HALF_UP),
-            (-999999, -1, HALF_UP),
+            (-1500000, -2, HALF_EVEN),
+            (-999999, -1, HALF_EVEN),
+            (-500000, 0, HALF_EVEN),
+            (500000, 0, HALF_EVEN),
+            (999999, 1, HALF_EVEN),
+            (1500000, 2, HALF_EVEN),
         ):
             with self.subTest(nanoseconds=ns, milliseconds=ms, round=rnd):
                 self.assertEqual(PyTime_AsMilliseconds(ns, rnd), ms)
@@ -1079,31 +1057,31 @@
 
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP = _PyTime.ROUND_HALF_UP
+        HALF_EVEN = _PyTime.ROUND_HALF_EVEN
         for ns, ms, rnd in (
             # nanoseconds
             (1, 0, FLOOR),
             (1, 1, CEILING),
-            (1, 0, HALF_UP),
-            (-1, 0, FLOOR),
-            (-1, -1, CEILING),
-            (-1, 0, HALF_UP),
+            (1, 0, HALF_EVEN),
+            (-1, -1, FLOOR),
+            (-1, 0, CEILING),
+            (-1, 0, HALF_EVEN),
 
             # seconds + nanoseconds
             (1234 * US_TO_NS + 1, 1234, FLOOR),
             (1234 * US_TO_NS + 1, 1235, CEILING),
-            (1234 * US_TO_NS + 1, 1234, HALF_UP),
-            (-1234 * US_TO_NS - 1, -1234, FLOOR),
-            (-1234 * US_TO_NS - 1, -1235, CEILING),
-            (-1234 * US_TO_NS - 1, -1234, HALF_UP),
+            (1234 * US_TO_NS + 1, 1234, HALF_EVEN),
+            (-1234 * US_TO_NS - 1, -1235, FLOOR),
+            (-1234 * US_TO_NS - 1, -1234, CEILING),
+            (-1234 * US_TO_NS - 1, -1234, HALF_EVEN),
 
             # half up
-            (1499, 1, HALF_UP),
-            (1500, 2, HALF_UP),
-            (1501, 2, HALF_UP),
-            (-1499, -1, HALF_UP),
-            (-1500, -2, HALF_UP),
-            (-1501, -2, HALF_UP),
+            (-1500, -2, HALF_EVEN),
+            (-999, -1, HALF_EVEN),
+            (-500, 0, HALF_EVEN),
+            (500, 0, HALF_EVEN),
+            (999, 1, HALF_EVEN),
+            (1500, 2, HALF_EVEN),
         ):
             with self.subTest(nanoseconds=ns, milliseconds=ms, round=rnd):
                 self.assertEqual(PyTime_AsMicroseconds(ns, rnd), ms)
@@ -1142,23 +1120,23 @@
         # Conversion giving different results depending on the rounding method
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP = _PyTime.ROUND_HALF_UP
+        HALF_EVEN = _PyTime.ROUND_HALF_EVEN
         for obj, time_t, rnd in (
             (-1.9, -2, FLOOR),
-            (-1.9, -2, HALF_UP),
+            (-1.9, -2, HALF_EVEN),
             (-1.9, -1, CEILING),
 
             (1.9, 1, FLOOR),
-            (1.9, 2, HALF_UP),
+            (1.9, 2, HALF_EVEN),
             (1.9, 2, CEILING),
 
-            (-0.6, -1, HALF_UP),
-            (-0.5, -1, HALF_UP),
-            (-0.4, 0, HALF_UP),
-
-            (0.4, 0, HALF_UP),
-            (0.5, 1, HALF_UP),
-            (0.6, 1, HALF_UP),
+            # half even
+            (-1.5, -2, HALF_EVEN),
+            (-0.9, -1, HALF_EVEN),
+            (-0.5,  0, HALF_EVEN),
+            ( 0.5,  0, HALF_EVEN),
+            ( 0.9,  1, HALF_EVEN),
+            ( 1.5,  2, HALF_EVEN),
         ):
             self.assertEqual(pytime_object_to_time_t(obj, rnd), time_t)
 
@@ -1192,29 +1170,27 @@
         # Conversion giving different results depending on the rounding method
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP = _PyTime.ROUND_HALF_UP
+        HALF_EVEN = _PyTime.ROUND_HALF_EVEN
         for obj, timeval, rnd in (
             (-1e-7, (-1, 999999), FLOOR),
             (-1e-7, (0, 0), CEILING),
-            (-1e-7, (0, 0), HALF_UP),
+            (-1e-7, (0, 0), HALF_EVEN),
 
             (1e-7, (0, 0), FLOOR),
             (1e-7, (0, 1), CEILING),
-            (1e-7, (0, 0), HALF_UP),
+            (1e-7, (0, 0), HALF_EVEN),
 
             (0.9999999, (0, 999999), FLOOR),
             (0.9999999, (1, 0), CEILING),
-            (0.9999999, (1, 0), HALF_UP),
+            (0.9999999, (1, 0), HALF_EVEN),
 
-            (-0.6e-6, (-1, 999999), HALF_UP),
-            # skipped, -0.5e-6 is inexact in base 2
-            #(-0.5e-6, (-1, 999999), HALF_UP),
-            (-0.4e-6, (0, 0), HALF_UP),
-
-            (0.4e-6, (0, 0), HALF_UP),
-            # skipped, 0.5e-6 is inexact in base 2
-            #(0.5e-6, (0, 1), HALF_UP),
-            (0.6e-6, (0, 1), HALF_UP),
+            # half even
+            (-1.5e-6, (-1, 999998), HALF_EVEN),
+            (-0.9e-6, (-1, 999999), HALF_EVEN),
+            (-0.5e-6, (0, 0), HALF_EVEN),
+            (0.5e-6, (0, 0), HALF_EVEN),
+            (0.9e-6, (0, 1), HALF_EVEN),
+            (1.5e-6, (0, 2), HALF_EVEN),
         ):
             with self.subTest(obj=obj, round=rnd, timeval=timeval):
                 self.assertEqual(pytime_object_to_timeval(obj, rnd), timeval)
@@ -1248,28 +1224,27 @@
         # Conversion giving different results depending on the rounding method
         FLOOR = _PyTime.ROUND_FLOOR
         CEILING = _PyTime.ROUND_CEILING
-        HALF_UP = _PyTime.ROUND_HALF_UP
+        HALF_EVEN = _PyTime.ROUND_HALF_EVEN
         for obj, timespec, rnd in (
             (-1e-10, (-1, 999999999), FLOOR),
             (-1e-10, (0, 0), CEILING),
-            (-1e-10, (0, 0), HALF_UP),
+            (-1e-10, (0, 0), HALF_EVEN),
 
             (1e-10, (0, 0), FLOOR),
             (1e-10, (0, 1), CEILING),
-            (1e-10, (0, 0), HALF_UP),
+            (1e-10, (0, 0), HALF_EVEN),
 
             (0.9999999999, (0, 999999999), FLOOR),
             (0.9999999999, (1, 0), CEILING),
-            (0.9999999999, (1, 0), HALF_UP),
+            (0.9999999999, (1, 0), HALF_EVEN),
 
-            (-0.6e-9, (-1, 999999999), HALF_UP),
-            # skipped, 0.5e-6 is inexact in base 2
-            #(-0.5e-9, (-1, 999999999), HALF_UP),
-            (-0.4e-9, (0, 0), HALF_UP),
-
-            (0.4e-9, (0, 0), HALF_UP),
-            (0.5e-9, (0, 1), HALF_UP),
-            (0.6e-9, (0, 1), HALF_UP),
+            # half even
+            (-1.5e-9, (-1, 999999998), HALF_EVEN),
+            (-0.9e-9, (-1, 999999999), HALF_EVEN),
+            (-0.5e-9, (0, 0), HALF_EVEN),
+            (0.5e-9, (0, 0), HALF_EVEN),
+            (0.9e-9, (0, 1), HALF_EVEN),
+            (1.5e-9, (0, 2), HALF_EVEN),
         ):
             with self.subTest(obj=obj, round=rnd, timespec=timespec):
                 self.assertEqual(pytime_object_to_timespec(obj, rnd), timespec)