From f81f0f9c63c8ae306d550b5bb387abf30e60a668 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 30 Mar 2015 00:44:06 +0200 Subject: Issue #22117: Fix rounding and implement _PyTime_ROUND_FLOOR in: - _PyTime_ObjectToTime_t() - _PyTime_ObjectToTimespec() - _PyTime_ObjectToTimeval() --- Lib/test/test_time.py | 4 ++-- Python/pytime.c | 44 ++++++++++++++++++++------------------------ 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index b0c97d5..bcbf41d 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -647,13 +647,13 @@ class TestPytime(unittest.TestCase): (1e-9, (0, 1), _PyTime.ROUND_DOWN), (1e-10, (0, 0), _PyTime.ROUND_DOWN), (-1e-9, (-1, 999999999), _PyTime.ROUND_DOWN), - (-1e-10, (-1, 999999999), _PyTime.ROUND_DOWN), + (-1e-10, (0, 0), _PyTime.ROUND_DOWN), (-1.2, (-2, 800000000), _PyTime.ROUND_DOWN), (0.9999999999, (0, 999999999), _PyTime.ROUND_DOWN), (1.1234567890, (1, 123456789), _PyTime.ROUND_DOWN), (1.1234567899, (1, 123456789), _PyTime.ROUND_DOWN), (-1.1234567890, (-2, 876543211), _PyTime.ROUND_DOWN), - (-1.1234567891, (-2, 876543210), _PyTime.ROUND_DOWN), + (-1.1234567891, (-2, 876543211), _PyTime.ROUND_DOWN), # Round away from zero (0, (0, 0), _PyTime.ROUND_UP), (-1, (-1, 0), _PyTime.ROUND_UP), diff --git a/Python/pytime.c b/Python/pytime.c index d9ff3c6..2bf6ba5 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -26,6 +26,14 @@ error_time_t_overflow(void) "timestamp out of range for platform time_t"); } +static int +_PyTime_RoundTowardsPosInf(int is_neg, _PyTime_round_t round) +{ + if (round == _PyTime_ROUND_FLOOR) + return 0; + return ((round == _PyTime_ROUND_UP) ^ is_neg); +} + time_t _PyLong_AsTime_t(PyObject *obj) { @@ -74,18 +82,16 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, } floatpart *= denominator; - if (round == _PyTime_ROUND_UP) { - if (intpart >= 0) { - floatpart = ceil(floatpart); - if (floatpart >= denominator) { - floatpart = 0.0; - intpart += 1.0; - } - } - else { - floatpart = floor(floatpart); + if (_PyTime_RoundTowardsPosInf(intpart < 0, round)) { + floatpart = ceil(floatpart); + if (floatpart >= denominator) { + floatpart = 0.0; + intpart += 1.0; } } + else { + floatpart = floor(floatpart); + } *sec = (time_t)intpart; err = intpart - (double)*sec; @@ -113,12 +119,10 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) double d, intpart, err; d = PyFloat_AsDouble(obj); - if (round == _PyTime_ROUND_UP) { - if (d >= 0) - d = ceil(d); - else - d = floor(d); - } + if (_PyTime_RoundTowardsPosInf(d < 0, round)) + d = ceil(d); + else + d = floor(d); (void)modf(d, &intpart); *sec = (time_t)intpart; @@ -158,14 +162,6 @@ _PyTime_overflow(void) "timestamp too large to convert to C _PyTime_t"); } -int -_PyTime_RoundTowardsPosInf(int is_neg, _PyTime_round_t round) -{ - if (round == _PyTime_ROUND_FLOOR) - return 0; - return ((round == _PyTime_ROUND_UP) ^ is_neg); -} - _PyTime_t _PyTime_FromNanoseconds(PY_LONG_LONG ns) { -- cgit v0.12