[Python-checkins] cpython: Revert change 0eb8c182131e:

victor.stinner python-checkins at python.org
Tue Sep 8 23:59:20 CEST 2015


https://hg.python.org/cpython/rev/d0bb896f9b14
changeset:   97781:d0bb896f9b14
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Tue Sep 08 23:58:54 2015 +0200
summary:
  Revert change 0eb8c182131e:

"""Issue #23517: datetime.timedelta constructor now rounds microseconds to
nearest with ties going away from zero (ROUND_HALF_UP), as Python 2 and Python
older than 3.3, instead of rounding to nearest with ties going to nearest even
integer (ROUND_HALF_EVEN)."""

datetime.timedelta uses rounding mode ROUND_HALF_EVEN again.

files:
  Lib/datetime.py            |   4 ++--
  Lib/test/datetimetester.py |  18 ++++++++++++------
  Misc/NEWS                  |   7 +------
  Modules/_datetimemodule.c  |  22 +++++++++++++++++++++-
  4 files changed, 36 insertions(+), 15 deletions(-)


diff --git a/Lib/datetime.py b/Lib/datetime.py
--- a/Lib/datetime.py
+++ b/Lib/datetime.py
@@ -407,7 +407,7 @@
         # secondsfrac isn't referenced again
 
         if isinstance(microseconds, float):
-            microseconds = _round_half_up(microseconds + usdouble)
+            microseconds = round(microseconds + usdouble)
             seconds, microseconds = divmod(microseconds, 1000000)
             days, seconds = divmod(seconds, 24*3600)
             d += days
@@ -418,7 +418,7 @@
             days, seconds = divmod(seconds, 24*3600)
             d += days
             s += seconds
-            microseconds = _round_half_up(microseconds + usdouble)
+            microseconds = round(microseconds + usdouble)
         assert isinstance(s, int)
         assert isinstance(microseconds, int)
         assert abs(s) <= 3 * 24 * 3600
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -663,14 +663,16 @@
         # Single-field rounding.
         eq(td(milliseconds=0.4/1000), td(0))    # rounds to 0
         eq(td(milliseconds=-0.4/1000), td(0))    # rounds to 0
-        eq(td(milliseconds=0.5/1000), td(microseconds=1))
-        eq(td(milliseconds=-0.5/1000), td(microseconds=-1))
+        eq(td(milliseconds=0.5/1000), td(microseconds=0))
+        eq(td(milliseconds=-0.5/1000), td(microseconds=-0))
         eq(td(milliseconds=0.6/1000), td(microseconds=1))
         eq(td(milliseconds=-0.6/1000), td(microseconds=-1))
-        eq(td(seconds=0.5/10**6), td(microseconds=1))
-        eq(td(seconds=-0.5/10**6), td(microseconds=-1))
-        eq(td(seconds=1/2**7), td(microseconds=7813))
-        eq(td(seconds=-1/2**7), td(microseconds=-7813))
+        eq(td(milliseconds=1.5/1000), td(microseconds=2))
+        eq(td(milliseconds=-1.5/1000), td(microseconds=-2))
+        eq(td(seconds=0.5/10**6), td(microseconds=0))
+        eq(td(seconds=-0.5/10**6), td(microseconds=-0))
+        eq(td(seconds=1/2**7), td(microseconds=7812))
+        eq(td(seconds=-1/2**7), td(microseconds=-7812))
 
         # Rounding due to contributions from more than one field.
         us_per_hour = 3600e6
@@ -683,6 +685,10 @@
         eq(td(hours=-.2/us_per_hour), td(0))
         eq(td(days=-.4/us_per_day, hours=-.2/us_per_hour), td(microseconds=-1))
 
+        # Test for a patch in Issue 8860
+        eq(td(microseconds=0.5), 0.5*td(microseconds=1.0))
+        eq(td(microseconds=0.5)//td.resolution, 0.5*td.resolution//td.resolution)
+
     def test_massive_normalization(self):
         td = timedelta(microseconds=-1)
         self.assertEqual((td.days, td.seconds, td.microseconds),
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -17,18 +17,13 @@
 Library
 -------
 
-- Issue #22241: timezone.utc name is now plain 'UTC', not 'UTC-00:00'. 
+- Issue #22241: timezone.utc name is now plain 'UTC', not 'UTC-00:00'.
 
 - Issue #23517: fromtimestamp() and utcfromtimestamp() methods of
   datetime.datetime now round microseconds to nearest with ties going away from
   zero (ROUND_HALF_UP), as Python 2 and Python older than 3.3, instead of
   rounding towards -Infinity (ROUND_FLOOR).
 
-- Issue #23517: datetime.timedelta constructor now rounds microseconds to
-  nearest with ties going away from zero (ROUND_HALF_UP), as Python 2 and
-  Python older than 3.3, instead of rounding to nearest with ties going to
-  nearest even integer (ROUND_HALF_EVEN).
-
 - Issue #23552: Timeit now warns when there is substantial (4x) variance
   between best and worst times. Patch from Serhiy Storchaka.
 
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -2149,9 +2149,29 @@
     if (leftover_us) {
         /* Round to nearest whole # of us, and add into x. */
         double whole_us = round(leftover_us);
+        int x_is_odd;
         PyObject *temp;
 
-        whole_us = _PyTime_RoundHalfUp(leftover_us);
+        whole_us = round(leftover_us);
+        if (fabs(whole_us - leftover_us) == 0.5) {
+            /* We're exactly halfway between two integers.  In order
+             * to do round-half-to-even, we must determine whether x
+             * is odd. Note that x is odd when it's last bit is 1. The
+             * code below uses bitwise and operation to check the last
+             * bit. */
+            temp = PyNumber_And(x, one);  /* temp <- x & 1 */
+            if (temp == NULL) {
+                Py_DECREF(x);
+                goto Done;
+            }
+            x_is_odd = PyObject_IsTrue(temp);
+            Py_DECREF(temp);
+            if (x_is_odd == -1) {
+                Py_DECREF(x);
+                goto Done;
+            }
+            whole_us = 2.0 * round((leftover_us + x_is_odd) * 0.5) - x_is_odd;
+        }
 
         temp = PyLong_FromLong((long)whole_us);
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list