[pypy-commit] pypy default: Try to fix rounding in datetime.fromtimestamp(). Mostly done
arigo
noreply at buildbot.pypy.org
Sat Jun 11 21:35:41 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r44888:c5617952be56
Date: 2011-06-11 21:37 +0200
http://bitbucket.org/pypy/pypy/changeset/c5617952be56/
Log: Try to fix rounding in datetime.fromtimestamp(). Mostly done by
trying out reasonable-looking alternatives until found one that
matches CPython's behavior. I *think* that the new test covers all
cases, so it should work.
diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py
--- a/lib_pypy/datetime.py
+++ b/lib_pypy/datetime.py
@@ -1422,12 +1422,17 @@
converter = _time.localtime
else:
converter = _time.gmtime
- if 1 - (t % 1.0) < 0.000001:
- t = float(int(t)) + 1
- if t < 0:
- t -= 1
+ if t < 0.0:
+ us = int(round(((-t) % 1.0) * 1000000))
+ if us > 0:
+ us = 1000000 - us
+ t -= 1.0
+ else:
+ us = int(round((t % 1.0) * 1000000))
+ if us == 1000000:
+ us = 0
+ t += 1.0
y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
- us = int((t % 1.0) * 1000000)
ss = min(ss, 59) # clamp out leap seconds if the platform has them
result = cls(y, m, d, hh, mm, ss, us, tz)
if tz is not None:
diff --git a/lib_pypy/pypy_test/test_datetime.py b/lib_pypy/pypy_test/test_datetime.py
--- a/lib_pypy/pypy_test/test_datetime.py
+++ b/lib_pypy/pypy_test/test_datetime.py
@@ -32,4 +32,28 @@
assert datetime.datetime.utcfromtimestamp(a).microsecond == 0
assert datetime.datetime.utcfromtimestamp(a).second == 1
-
+def test_more_datetime_rounding():
+ # this test verified on top of CPython 2.7 (using a plain
+ # "import datetime" above)
+ expected_results = {
+ -1000.0: 'datetime.datetime(1970, 1, 1, 0, 43, 20)',
+ -999.9999996: 'datetime.datetime(1970, 1, 1, 0, 43, 20)',
+ -999.4: 'datetime.datetime(1970, 1, 1, 0, 43, 20, 600000)',
+ -999.0000004: 'datetime.datetime(1970, 1, 1, 0, 43, 21)',
+ -1.0: 'datetime.datetime(1970, 1, 1, 0, 59, 59)',
+ -0.9999996: 'datetime.datetime(1970, 1, 1, 0, 59, 59)',
+ -0.4: 'datetime.datetime(1970, 1, 1, 0, 59, 59, 600000)',
+ -0.0000004: 'datetime.datetime(1970, 1, 1, 1, 0)',
+ 0.0: 'datetime.datetime(1970, 1, 1, 1, 0)',
+ 0.0000004: 'datetime.datetime(1970, 1, 1, 1, 0)',
+ 0.4: 'datetime.datetime(1970, 1, 1, 1, 0, 0, 400000)',
+ 0.9999996: 'datetime.datetime(1970, 1, 1, 1, 0, 1)',
+ 1000.0: 'datetime.datetime(1970, 1, 1, 1, 16, 40)',
+ 1000.0000004: 'datetime.datetime(1970, 1, 1, 1, 16, 40)',
+ 1000.4: 'datetime.datetime(1970, 1, 1, 1, 16, 40, 400000)',
+ 1000.9999996: 'datetime.datetime(1970, 1, 1, 1, 16, 41)',
+ 1293843661.191: 'datetime.datetime(2011, 1, 1, 2, 1, 1, 191000)',
+ }
+ for t in sorted(expected_results):
+ dt = datetime.datetime.fromtimestamp(t)
+ assert repr(dt) == expected_results[t]
More information about the pypy-commit
mailing list