mirror of
https://github.com/python/cpython.git
synced 2025-07-12 13:55:34 +00:00
Issue #23517: Fix implementation of the ROUND_HALF_UP rounding mode in
datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp(). microseconds sign should be kept before rounding.
This commit is contained in:
parent
19bbb9af67
commit
adfefa527a
4 changed files with 43 additions and 40 deletions
|
@ -1373,6 +1373,26 @@ class datetime(date):
|
|||
"""timezone info object"""
|
||||
return self._tzinfo
|
||||
|
||||
@classmethod
|
||||
def _fromtimestamp(cls, t, utc, tz):
|
||||
"""Construct a datetime from a POSIX timestamp (like time.time()).
|
||||
|
||||
A timezone info object may be passed in as well.
|
||||
"""
|
||||
frac, t = _math.modf(t)
|
||||
us = _round_half_up(frac * 1e6)
|
||||
if us >= 1000000:
|
||||
t += 1
|
||||
us -= 1000000
|
||||
elif us < 0:
|
||||
t -= 1
|
||||
us += 1000000
|
||||
|
||||
converter = _time.gmtime if utc else _time.localtime
|
||||
y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
|
||||
ss = min(ss, 59) # clamp out leap seconds if the platform has them
|
||||
return cls(y, m, d, hh, mm, ss, us, tz)
|
||||
|
||||
@classmethod
|
||||
def fromtimestamp(cls, t, tz=None):
|
||||
"""Construct a datetime from a POSIX timestamp (like time.time()).
|
||||
|
@ -1381,21 +1401,7 @@ class datetime(date):
|
|||
"""
|
||||
_check_tzinfo_arg(tz)
|
||||
|
||||
converter = _time.localtime if tz is None else _time.gmtime
|
||||
|
||||
t, frac = divmod(t, 1.0)
|
||||
us = _round_half_up(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)
|
||||
ss = min(ss, 59) # clamp out leap seconds if the platform has them
|
||||
result = cls(y, m, d, hh, mm, ss, us, tz)
|
||||
result = cls._fromtimestamp(t, tz is not None, tz)
|
||||
if tz is not None:
|
||||
result = tz.fromutc(result)
|
||||
return result
|
||||
|
@ -1403,19 +1409,7 @@ class datetime(date):
|
|||
@classmethod
|
||||
def utcfromtimestamp(cls, t):
|
||||
"""Construct a naive UTC datetime from a POSIX timestamp."""
|
||||
t, frac = divmod(t, 1.0)
|
||||
us = _round_half_up(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 = _time.gmtime(t)
|
||||
ss = min(ss, 59) # clamp out leap seconds if the platform has them
|
||||
return cls(y, m, d, hh, mm, ss, us)
|
||||
return cls._fromtimestamp(t, True, None)
|
||||
|
||||
@classmethod
|
||||
def now(cls, tz=None):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue