]> granicus.if.org Git - python/commitdiff
Issue #22117: Add _PyTime_ROUND_CEILING rounding method for timestamps
authorVictor Stinner <victor.stinner@gmail.com>
Mon, 30 Mar 2015 01:52:49 +0000 (03:52 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Mon, 30 Mar 2015 01:52:49 +0000 (03:52 +0200)
Add also more tests for ROUNd_FLOOR.

Include/pytime.h
Lib/test/test_time.py
Modules/_testcapimodule.c
Python/pytime.c

index f14e1fc6fde5063e0076aad00a7f94547f8a0685..ff3e203e359b3ecc832f3cdd18f9d5895b154da9 100644 (file)
@@ -32,7 +32,10 @@ typedef enum {
     _PyTime_ROUND_UP,
     /* Round towards minus infinity (-inf).
        For example, used to read a clock. */
-    _PyTime_ROUND_FLOOR
+    _PyTime_ROUND_FLOOR,
+    /* Round towards infinity (+inf).
+       For example, used for timeout to wait "at least" N seconds. */
+    _PyTime_ROUND_CEILING
 } _PyTime_round_t;
 
 /* Convert a time_t to a PyLong. */
index bcbf41d0db85bee774479fcdeccf6e16c6af1e1f..472110c687aef467757531d9333f726f47c62061 100644 (file)
@@ -28,13 +28,16 @@ class _PyTime(enum.IntEnum):
     ROUND_DOWN = 0
     # Round away from zero
     ROUND_UP = 1
-    # Round towards -Infinity
+    # Round towards minus infinity (-inf)
     ROUND_FLOOR = 2
+    # Round towards infinity (+inf)
+    ROUND_CEILING = 3
 
 ALL_ROUNDING_METHODS = (
     _PyTime.ROUND_UP,
     _PyTime.ROUND_DOWN,
-    _PyTime.ROUND_FLOOR)
+    _PyTime.ROUND_FLOOR,
+    _PyTime.ROUND_CEILING)
 
 
 class TimeTestCase(unittest.TestCase):
@@ -621,6 +624,13 @@ class TestPytime(unittest.TestCase):
             (-1.9, -1, _PyTime.ROUND_DOWN),
             (1.0, 1, _PyTime.ROUND_DOWN),
             (1.9, 1, _PyTime.ROUND_DOWN),
+            # Round towards minus infinity (-inf)
+            (0, 0, _PyTime.ROUND_FLOOR),
+            (-1, -1, _PyTime.ROUND_FLOOR),
+            (-1.0, -1, _PyTime.ROUND_FLOOR),
+            (-1.9, -2, _PyTime.ROUND_FLOOR),
+            (1.0, 1, _PyTime.ROUND_FLOOR),
+            (1.9, 1, _PyTime.ROUND_FLOOR),
             # Round away from zero
             (0, 0, _PyTime.ROUND_UP),
             (-1, -1, _PyTime.ROUND_UP),
@@ -628,10 +638,17 @@ class TestPytime(unittest.TestCase):
             (-1.9, -2, _PyTime.ROUND_UP),
             (1.0, 1, _PyTime.ROUND_UP),
             (1.9, 2, _PyTime.ROUND_UP),
+            # Round towards infinity (+inf)
+            (0, 0, _PyTime.ROUND_CEILING),
+            (-1, -1, _PyTime.ROUND_CEILING),
+            (-1.0, -1, _PyTime.ROUND_CEILING),
+            (-1.9, -1, _PyTime.ROUND_CEILING),
+            (1.0, 1, _PyTime.ROUND_CEILING),
+            (1.9, 2, _PyTime.ROUND_CEILING),
         ):
             self.assertEqual(pytime_object_to_time_t(obj, rnd), time_t)
 
-        rnd = _PyTime.ROUND_DOWN
+        rnd = _PyTime.ROUND_FLOOR
         for invalid in self.invalid_values:
             self.assertRaises(OverflowError,
                               pytime_object_to_time_t, invalid, rnd)
@@ -654,6 +671,20 @@ class TestPytime(unittest.TestCase):
             (1.1234567899, (1, 123456789), _PyTime.ROUND_DOWN),
             (-1.1234567890, (-2, 876543211), _PyTime.ROUND_DOWN),
             (-1.1234567891, (-2, 876543211), _PyTime.ROUND_DOWN),
+            # Round towards minus infinity (-inf)
+            (0, (0, 0), _PyTime.ROUND_FLOOR),
+            (-1, (-1, 0), _PyTime.ROUND_FLOOR),
+            (-1.0, (-1, 0), _PyTime.ROUND_FLOOR),
+            (1e-9, (0, 1), _PyTime.ROUND_FLOOR),
+            (1e-10, (0, 0), _PyTime.ROUND_FLOOR),
+            (-1e-9, (-1, 999999999), _PyTime.ROUND_FLOOR),
+            (-1e-10, (-1, 999999999), _PyTime.ROUND_FLOOR),
+            (-1.2, (-2, 800000000), _PyTime.ROUND_FLOOR),
+            (0.9999999999, (0, 999999999), _PyTime.ROUND_FLOOR),
+            (1.1234567890, (1, 123456789), _PyTime.ROUND_FLOOR),
+            (1.1234567899, (1, 123456789), _PyTime.ROUND_FLOOR),
+            (-1.1234567890, (-2, 876543211), _PyTime.ROUND_FLOOR),
+            (-1.1234567891, (-2, 876543210), _PyTime.ROUND_FLOOR),
             # Round away from zero
             (0, (0, 0), _PyTime.ROUND_UP),
             (-1, (-1, 0), _PyTime.ROUND_UP),
@@ -668,11 +699,25 @@ class TestPytime(unittest.TestCase):
             (1.1234567899, (1, 123456790), _PyTime.ROUND_UP),
             (-1.1234567890, (-2, 876543211), _PyTime.ROUND_UP),
             (-1.1234567891, (-2, 876543210), _PyTime.ROUND_UP),
+            # Round towards infinity (+inf)
+            (0, (0, 0), _PyTime.ROUND_CEILING),
+            (-1, (-1, 0), _PyTime.ROUND_CEILING),
+            (-1.0, (-1, 0), _PyTime.ROUND_CEILING),
+            (1e-9, (0, 1), _PyTime.ROUND_CEILING),
+            (1e-10, (0, 1), _PyTime.ROUND_CEILING),
+            (-1e-9, (-1, 999999999), _PyTime.ROUND_CEILING),
+            (-1e-10, (0, 0), _PyTime.ROUND_CEILING),
+            (-1.2, (-2, 800000000), _PyTime.ROUND_CEILING),
+            (0.9999999999, (1, 0), _PyTime.ROUND_CEILING),
+            (1.1234567890, (1, 123456790), _PyTime.ROUND_CEILING),
+            (1.1234567899, (1, 123456790), _PyTime.ROUND_CEILING),
+            (-1.1234567890, (-2, 876543211), _PyTime.ROUND_CEILING),
+            (-1.1234567891, (-2, 876543211), _PyTime.ROUND_CEILING),
         ):
             with self.subTest(obj=obj, round=rnd, timespec=timespec):
                 self.assertEqual(pytime_object_to_timespec(obj, rnd), timespec)
 
-        rnd = _PyTime.ROUND_DOWN
+        rnd = _PyTime.ROUND_FLOOR
         for invalid in self.invalid_values:
             self.assertRaises(OverflowError,
                               pytime_object_to_timespec, invalid, rnd)
@@ -794,27 +839,34 @@ class TestPyTime_t(unittest.TestCase):
         UP = _PyTime.ROUND_UP
         DOWN = _PyTime.ROUND_DOWN
         FLOOR = _PyTime.ROUND_FLOOR
+        CEILING = _PyTime.ROUND_CEILING
         for obj, ts, rnd in (
             # close to zero
+            ( 1e-10,  1, CEILING),
             ( 1e-10,  1, UP),
             ( 1e-10,  0, DOWN),
             ( 1e-10,  0, FLOOR),
+            (-1e-10,  0, CEILING),
             (-1e-10,  0, DOWN),
             (-1e-10, -1, UP),
             (-1e-10, -1, FLOOR),
 
             # test rounding of the last nanosecond
+            ( 1.1234567899,  1123456790, CEILING),
             ( 1.1234567899,  1123456790, UP),
             ( 1.1234567899,  1123456789, DOWN),
             ( 1.1234567899,  1123456789, FLOOR),
+            (-1.1234567899, -1123456789, CEILING),
             (-1.1234567899, -1123456789, DOWN),
             (-1.1234567899, -1123456790, UP),
             (-1.1234567899, -1123456790, FLOOR),
 
             # close to 1 second
+            ( 0.9999999999,  1000000000, CEILING),
             ( 0.9999999999,  1000000000, UP),
             ( 0.9999999999,   999999999, DOWN),
             ( 0.9999999999,   999999999, FLOOR),
+            (-0.9999999999,  -999999999, CEILING),
             (-0.9999999999,  -999999999, DOWN),
             (-0.9999999999, -1000000000, UP),
             (-0.9999999999, -1000000000, FLOOR),
@@ -890,19 +942,24 @@ class TestPyTime_t(unittest.TestCase):
         UP = _PyTime.ROUND_UP
         DOWN = _PyTime.ROUND_DOWN
         FLOOR = _PyTime.ROUND_FLOOR
+        CEILING = _PyTime.ROUND_CEILING
         for ns, tv, rnd in (
             # nanoseconds
+            (1, (0, 1), CEILING),
             (1, (0, 1), UP),
             (1, (0, 0), DOWN),
             (1, (0, 0), FLOOR),
+            (-1, (0, 0), CEILING),
             (-1, (0, 0), DOWN),
             (-1, (-1, 999999), UP),
             (-1, (-1, 999999), FLOOR),
 
             # seconds + nanoseconds
+            (1234567001, (1, 234568), CEILING),
             (1234567001, (1, 234568), UP),
             (1234567001, (1, 234567), DOWN),
             (1234567001, (1, 234567), FLOOR),
+            (-1234567001, (-2, 765433), CEILING),
             (-1234567001, (-2, 765433), DOWN),
             (-1234567001, (-2, 765432), UP),
             (-1234567001, (-2, 765432), FLOOR),
index 128ba094b2ee9aff185958b8ffd95915393209de..25f916beb9e389b246f3135ac8001b956e267403 100644 (file)
@@ -2635,7 +2635,7 @@ static int
 check_time_rounding(int round)
 {
     if (round != _PyTime_ROUND_DOWN && round != _PyTime_ROUND_UP
-        && round != _PyTime_ROUND_FLOOR) {
+        && round != _PyTime_ROUND_FLOOR && round != _PyTime_ROUND_CEILING) {
         PyErr_SetString(PyExc_ValueError, "invalid rounding");
         return -1;
     }
index 0d28911c378600aa27e531d0700d33a878bb718d..ca4386aa089c7a488f705dbf00e076fda49fbe7c 100644 (file)
@@ -31,6 +31,8 @@ _PyTime_RoundTowardsPosInf(int is_neg, _PyTime_round_t round)
 {
     if (round == _PyTime_ROUND_FLOOR)
         return 0;
+    if (round == _PyTime_ROUND_CEILING)
+        return 1;
     return ((round == _PyTime_ROUND_UP) ^ is_neg);
 }