_PyTime_AsMicroseconds() rounding. Add also unit tests.
This commit is contained in:
parent
067bbba7a4
commit
62d1c70eff
|
@ -21,6 +21,8 @@ SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4
|
|||
TIME_MAXYEAR = (1 << 8 * SIZEOF_INT - 1) - 1
|
||||
TIME_MINYEAR = -TIME_MAXYEAR - 1
|
||||
|
||||
US_TO_NS = 10 ** 3
|
||||
MS_TO_NS = 10 ** 6
|
||||
SEC_TO_NS = 10 ** 9
|
||||
|
||||
class _PyTime(enum.IntEnum):
|
||||
|
@ -867,10 +869,6 @@ class TestPyTime_t(unittest.TestCase):
|
|||
# seconds
|
||||
(2 * SEC_TO_NS, (2, 0)),
|
||||
(-3 * SEC_TO_NS, (-3, 0)),
|
||||
|
||||
# seconds + nanoseconds
|
||||
(1234567000, (1, 234567)),
|
||||
(-1234567000, (-2, 765433)),
|
||||
):
|
||||
with self.subTest(nanoseconds=ns, timeval=tv, round=rnd):
|
||||
self.assertEqual(PyTime_AsTimeval(ns, rnd), tv)
|
||||
|
@ -914,6 +912,76 @@ class TestPyTime_t(unittest.TestCase):
|
|||
with self.subTest(nanoseconds=ns, timespec=ts):
|
||||
self.assertEqual(PyTime_AsTimespec(ns), ts)
|
||||
|
||||
def test_milliseconds(self):
|
||||
from _testcapi import PyTime_AsMilliseconds
|
||||
for rnd in ALL_ROUNDING_METHODS:
|
||||
for ns, tv in (
|
||||
# milliseconds
|
||||
(1 * MS_TO_NS, 1),
|
||||
(-2 * MS_TO_NS, -2),
|
||||
|
||||
# seconds
|
||||
(2 * SEC_TO_NS, 2000),
|
||||
(-3 * SEC_TO_NS, -3000),
|
||||
):
|
||||
with self.subTest(nanoseconds=ns, timeval=tv, round=rnd):
|
||||
self.assertEqual(PyTime_AsMilliseconds(ns, rnd), tv)
|
||||
|
||||
FLOOR = _PyTime.ROUND_FLOOR
|
||||
CEILING = _PyTime.ROUND_CEILING
|
||||
for ns, ms, rnd in (
|
||||
# nanoseconds
|
||||
(1, 0, FLOOR),
|
||||
(1, 1, CEILING),
|
||||
(-1, 0, FLOOR),
|
||||
(-1, -1, CEILING),
|
||||
|
||||
# seconds + nanoseconds
|
||||
(1234 * MS_TO_NS + 1, 1234, FLOOR),
|
||||
(1234 * MS_TO_NS + 1, 1235, CEILING),
|
||||
(-1234 * MS_TO_NS - 1, -1234, FLOOR),
|
||||
(-1234 * MS_TO_NS - 1, -1235, CEILING),
|
||||
):
|
||||
with self.subTest(nanoseconds=ns, milliseconds=ms, round=rnd):
|
||||
self.assertEqual(PyTime_AsMilliseconds(ns, rnd), ms)
|
||||
|
||||
def test_microseconds(self):
|
||||
from _testcapi import PyTime_AsMicroseconds
|
||||
for rnd in ALL_ROUNDING_METHODS:
|
||||
for ns, tv in (
|
||||
# microseconds
|
||||
(1 * US_TO_NS, 1),
|
||||
(-2 * US_TO_NS, -2),
|
||||
|
||||
# milliseconds
|
||||
(1 * MS_TO_NS, 1000),
|
||||
(-2 * MS_TO_NS, -2000),
|
||||
|
||||
# seconds
|
||||
(2 * SEC_TO_NS, 2000000),
|
||||
(-3 * SEC_TO_NS, -3000000),
|
||||
):
|
||||
with self.subTest(nanoseconds=ns, timeval=tv, round=rnd):
|
||||
self.assertEqual(PyTime_AsMicroseconds(ns, rnd), tv)
|
||||
|
||||
FLOOR = _PyTime.ROUND_FLOOR
|
||||
CEILING = _PyTime.ROUND_CEILING
|
||||
for ns, ms, rnd in (
|
||||
# nanoseconds
|
||||
(1, 0, FLOOR),
|
||||
(1, 1, CEILING),
|
||||
(-1, 0, FLOOR),
|
||||
(-1, -1, CEILING),
|
||||
|
||||
# seconds + nanoseconds
|
||||
(1234 * US_TO_NS + 1, 1234, FLOOR),
|
||||
(1234 * US_TO_NS + 1, 1235, CEILING),
|
||||
(-1234 * US_TO_NS - 1, -1234, FLOOR),
|
||||
(-1234 * US_TO_NS - 1, -1235, CEILING),
|
||||
):
|
||||
with self.subTest(nanoseconds=ns, milliseconds=ms, round=rnd):
|
||||
self.assertEqual(PyTime_AsMicroseconds(ns, rnd), ms)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -3452,6 +3452,42 @@ test_PyTime_AsTimespec(PyObject *self, PyObject *args)
|
|||
}
|
||||
#endif
|
||||
|
||||
static PyObject *
|
||||
test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
|
||||
{
|
||||
PY_LONG_LONG ns;
|
||||
int round;
|
||||
_PyTime_t t, ms;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Li", &ns, &round))
|
||||
return NULL;
|
||||
if (check_time_rounding(round) < 0)
|
||||
return NULL;
|
||||
t = _PyTime_FromNanoseconds(ns);
|
||||
ms = _PyTime_AsMilliseconds(t, round);
|
||||
/* This conversion rely on the fact that _PyTime_t is a number of
|
||||
nanoseconds */
|
||||
return _PyTime_AsNanosecondsObject(ms);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
|
||||
{
|
||||
PY_LONG_LONG ns;
|
||||
int round;
|
||||
_PyTime_t t, ms;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Li", &ns, &round))
|
||||
return NULL;
|
||||
if (check_time_rounding(round) < 0)
|
||||
return NULL;
|
||||
t = _PyTime_FromNanoseconds(ns);
|
||||
ms = _PyTime_AsMicroseconds(t, round);
|
||||
/* This conversion rely on the fact that _PyTime_t is a number of
|
||||
nanoseconds */
|
||||
return _PyTime_AsNanosecondsObject(ms);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef TestMethods[] = {
|
||||
{"raise_exception", raise_exception, METH_VARARGS},
|
||||
|
@ -3621,6 +3657,8 @@ static PyMethodDef TestMethods[] = {
|
|||
#ifdef HAVE_CLOCK_GETTIME
|
||||
{"PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS},
|
||||
#endif
|
||||
{"PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS},
|
||||
{"PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
#define MS_TO_NS (MS_TO_US * US_TO_NS)
|
||||
#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)
|
||||
|
||||
/* Conversion from nanoseconds */
|
||||
#define NS_TO_MS (1000 * 1000)
|
||||
#define NS_TO_US (1000)
|
||||
|
||||
static void
|
||||
error_time_t_overflow(void)
|
||||
{
|
||||
|
@ -288,33 +292,29 @@ _PyTime_AsNanosecondsObject(_PyTime_t t)
|
|||
}
|
||||
|
||||
static _PyTime_t
|
||||
_PyTime_Multiply(_PyTime_t t, unsigned int multiply, _PyTime_round_t round)
|
||||
_PyTime_Divide(_PyTime_t t, _PyTime_t k, _PyTime_round_t round)
|
||||
{
|
||||
_PyTime_t k;
|
||||
if (multiply < SEC_TO_NS) {
|
||||
k = SEC_TO_NS / multiply;
|
||||
if (round == _PyTime_ROUND_CEILING)
|
||||
assert(k > 1);
|
||||
if (round == _PyTime_ROUND_CEILING) {
|
||||
if (t >= 0)
|
||||
return (t + k - 1) / k;
|
||||
else
|
||||
return (t - (k - 1)) / k;
|
||||
}
|
||||
else
|
||||
return t / k;
|
||||
}
|
||||
else {
|
||||
k = multiply / SEC_TO_NS;
|
||||
return t * k;
|
||||
}
|
||||
}
|
||||
|
||||
_PyTime_t
|
||||
_PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round)
|
||||
{
|
||||
return _PyTime_Multiply(t, 1000, round);
|
||||
return _PyTime_Divide(t, NS_TO_MS, round);
|
||||
}
|
||||
|
||||
/* FIXME: write unit tests */
|
||||
_PyTime_t
|
||||
_PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round)
|
||||
{
|
||||
return _PyTime_Multiply(t, 1000 * 1000, round);
|
||||
return _PyTime_Divide(t, NS_TO_US, round);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Loading…
Reference in New Issue