Skip to content

Commit

Permalink
Eliminate the call to round() in the Python TimeStamp constructor.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Aug 6, 2018
1 parent fba4985 commit e00b287
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 13 deletions.
13 changes: 7 additions & 6 deletions CHANGES.rst
Expand Up @@ -31,12 +31,13 @@
- Remove some internal compatibility shims that are no longer
necessary. See `PR 82 <https://github.com/zopefoundation/persistent/pull/82>`_.

- The precision of ``TimeStamp`` objects created from 6 arguments with
floating point seconds values matches across C and Python, and
matches across trips through ``TimeStamp.raw()``. Previously, the C
version could initially have erroneous rounding and too much
false precision, while the Python version could have too much
precision. The raw/repr values have not changed. See `issue 41
- Make the return value of ``TimeStamp.second()`` consistent across C
and Python implementations when the ``TimeStamp`` was created from 6
arguments with floating point seconds. Also make it match across
trips through ``TimeStamp.raw()``. Previously, the C version could
initially have erroneous rounding and too much false precision,
while the Python version could have too much precision. The raw/repr
values have not changed. See `issue 41
<https://github.com/zopefoundation/persistent/issues/41>`_.

4.3.0 (2018-07-30)
Expand Down
4 changes: 2 additions & 2 deletions persistent/_timestamp.c
Expand Up @@ -202,8 +202,8 @@ TimeStamp_sec(TimeStamp *self)
v = (self->data[4] * 16777216 + self->data[5] * 65536
+ self->data[6] * 256 + self->data[7]);
sec = SCONV * (double)v;
/* always round to 6 places for consistency; that's going to
happen after a trip through raw() */
/* always round to 6 places for consistency with the Python version.
We really only record that level of precision anyway. */
#if defined(_MSC_VER) && _MSC_VER <= 1600
/* the windows compilers for Python 2.7 and 3.4 don't support C99
round(). 1600 is visual studio 10, aka 2010, used for 3.4 */
Expand Down
12 changes: 7 additions & 5 deletions persistent/timestamp.py
Expand Up @@ -83,24 +83,26 @@ class pyTimeStamp(object):
__slots__ = ('_raw', '_elements')

def __init__(self, *args):
self._elements = None
if len(args) == 1:
raw = args[0]
if not isinstance(raw, _RAWTYPE):
raise TypeError('Raw octets must be of type: %s' % _RAWTYPE)
if len(raw) != 8:
raise TypeError('Raw must be 8 octets')
self._raw = raw
self._elements = _parseRaw(raw)
elif len(args) == 6:
self._raw = _makeRaw(*args)
self._elements = args[:5]
# Be sure to round the reported seconds value, just as we will
# after a trip through raw()
self._elements += (round(args[5], 6),)
# Note that we don't preserve the incoming arguments in self._elements,
# we derive them from the raw value. This is because the incoming
# seconds value could have more precision than would survive
# in the raw data, so we must be consistent.
else:
raise TypeError('Pass either a single 8-octet arg '
'or 5 integers and a float')

self._elements = _parseRaw(self._raw)

def raw(self):
return self._raw

Expand Down

0 comments on commit e00b287

Please sign in to comment.