Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit aeb0398

Browse files
committed
Make python version of fromtimestamp behave more like C.
1 parent 0f0c332 commit aeb0398

2 files changed

Lines changed: 20 additions & 10 deletions

File tree

Lib/datetime.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,16 +1356,20 @@ def fromtimestamp(cls, t, tz=None):
13561356
"""
13571357

13581358
_check_tzinfo_arg(tz)
1359-
if tz is None:
1360-
converter = _time.localtime
1361-
else:
1362-
converter = _time.gmtime
1363-
if 1 - (t % 1.0) < 0.000001:
1364-
t = float(int(t)) + 1
1365-
if t < 0:
1366-
t -= 1
1359+
1360+
converter = _time.localtime if tz is None else _time.gmtime
1361+
1362+
t, frac = divmod(t, 1.0)
1363+
us = round(frac * 1e6)
1364+
1365+
# If timestamp is less than one microsecond smaller than a
1366+
# full second, us can be rounded up to 1000000. In this case,
1367+
# roll over to seconds, otherwise, ValueError is raised
1368+
# by the constructor.
1369+
if us == 1000000:
1370+
t += 1
1371+
us = 0
13671372
y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
1368-
us = int((t % 1.0) * 1000000)
13691373
ss = min(ss, 59) # clamp out leap seconds if the platform has them
13701374
result = cls(y, m, d, hh, mm, ss, us, tz)
13711375
if tz is not None:

Lib/test/datetimetester.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1728,9 +1728,15 @@ def test_utcfromtimestamp(self):
17281728

17291729
def test_microsecond_rounding(self):
17301730
# Test whether fromtimestamp "rounds up" floats that are less
1731-
# than one microsecond smaller than an integer.
1731+
# than 1/2 microsecond smaller than an integer.
17321732
self.assertEqual(self.theclass.fromtimestamp(0.9999999),
17331733
self.theclass.fromtimestamp(1))
1734+
self.assertEqual(self.theclass.fromtimestamp(0.99999949).microsecond,
1735+
999999)
1736+
# XXX Arguably incorrect behavior. Since round(0.6112295, 6)
1737+
# returns 0.611229, we should see 611229 us below, not 611230
1738+
self.assertEqual(self.theclass.fromtimestamp(0.6112295).microsecond,
1739+
611230)
17341740

17351741
def test_insane_fromtimestamp(self):
17361742
# It's possible that some platform maps time_t to double,

0 commit comments

Comments
 (0)