summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>2010-07-26 02:36:41 (GMT)
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>2010-07-26 02:36:41 (GMT)
commitaeb039863d2962dcffa60823d9afab2c39c8d8fc (patch)
tree5844b8d3c9245c4bc365d39e9454c78944305f4f
parent0f0c3320ee82a16d57f76ac96a781379e61e3296 (diff)
downloadcpython-aeb039863d2962dcffa60823d9afab2c39c8d8fc.zip
cpython-aeb039863d2962dcffa60823d9afab2c39c8d8fc.tar.gz
cpython-aeb039863d2962dcffa60823d9afab2c39c8d8fc.tar.bz2
Make python version of fromtimestamp behave more like C.
-rw-r--r--Lib/datetime.py22
-rw-r--r--Lib/test/datetimetester.py8
2 files changed, 20 insertions, 10 deletions
diff --git a/Lib/datetime.py b/Lib/datetime.py
index 19f20e7..23ded3e 100644
--- a/Lib/datetime.py
+++ b/Lib/datetime.py
@@ -1356,16 +1356,20 @@ class datetime(date):
"""
_check_tzinfo_arg(tz)
- if tz is None:
- converter = _time.localtime
- else:
- converter = _time.gmtime
- if 1 - (t % 1.0) < 0.000001:
- t = float(int(t)) + 1
- if t < 0:
- t -= 1
+
+ converter = _time.localtime if tz is None else _time.gmtime
+
+ t, frac = divmod(t, 1.0)
+ us = round(frac * 1e6)
+
+ # If timestamp is less than one microsecond smaller than a
+ # full second, us can be rounded up to 1000000. In this case,
+ # roll over to seconds, otherwise, ValueError is raised
+ # by the constructor.
+ if us == 1000000:
+ t += 1
+ us = 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/test/datetimetester.py b/Lib/test/datetimetester.py
index 8be72a4..8dd0326 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -1728,9 +1728,15 @@ class TestDateTime(TestDate):
def test_microsecond_rounding(self):
# Test whether fromtimestamp "rounds up" floats that are less
- # than one microsecond smaller than an integer.
+ # than 1/2 microsecond smaller than an integer.
self.assertEqual(self.theclass.fromtimestamp(0.9999999),
self.theclass.fromtimestamp(1))
+ self.assertEqual(self.theclass.fromtimestamp(0.99999949).microsecond,
+ 999999)
+ # XXX Arguably incorrect behavior. Since round(0.6112295, 6)
+ # returns 0.611229, we should see 611229 us below, not 611230
+ self.assertEqual(self.theclass.fromtimestamp(0.6112295).microsecond,
+ 611230)
def test_insane_fromtimestamp(self):
# It's possible that some platform maps time_t to double,