From ef5edd0ba5df78362bec1baec84659f5fa6ef315 Mon Sep 17 00:00:00 2001 From: Adam Holmberg Date: Wed, 23 Mar 2016 15:12:57 -0500 Subject: [PATCH] cython: emulate cpython rounding for datetime deserialization PYTHON-480 --- cassandra/cython_utils.pyx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/cassandra/cython_utils.pyx b/cassandra/cython_utils.pyx index c9caf01f..3c6fae03 100644 --- a/cassandra/cython_utils.pyx +++ b/cassandra/cython_utils.pyx @@ -17,6 +17,8 @@ Duplicate module of util.py, with some accelerated functions used for deserialization. """ +from libc.math cimport modf, round, fabs + from cpython.datetime cimport ( timedelta_new, # cdef inline object timedelta_new(int days, int seconds, int useconds) @@ -44,6 +46,17 @@ cdef datetime_from_timestamp(double timestamp): cdef int days = (timestamp / DAY_IN_SECONDS) cdef int64_t days_in_seconds = ( days) * DAY_IN_SECONDS cdef int seconds = (timestamp - days_in_seconds) - cdef int microseconds = ((timestamp - days_in_seconds - seconds) * 1000000) + cdef double tmp + cdef double micros_left = modf(timestamp, &tmp) * 1000000. + micros_left = modf(micros_left, &tmp) + cdef int microseconds = tmp + + # rounding to emulate fp math in delta_new + cdef int x_odd + tmp = round(micros_left) + if fabs(tmp - micros_left) == 0.5: + x_odd = microseconds & 1 + tmp = 2.0 * round((micros_left + x_odd) * 0.5) - x_odd + microseconds += tmp return DATETIME_EPOC + timedelta_new(days, seconds, microseconds)