mirror of https://github.com/python/cpython
gh-83861: Fix datetime.astimezone() method (GH-101545)
This commit is contained in:
parent
d4aa8578b1
commit
2b1260c557
|
@ -1965,6 +1965,11 @@ class datetime(date):
|
|||
def _local_timezone(self):
|
||||
if self.tzinfo is None:
|
||||
ts = self._mktime()
|
||||
# Detect gap
|
||||
ts2 = self.replace(fold=1-self.fold)._mktime()
|
||||
if ts2 != ts: # This happens in a gap or a fold
|
||||
if (ts2 > ts) == self.fold:
|
||||
ts = ts2
|
||||
else:
|
||||
ts = (self - _EPOCH) // timedelta(seconds=1)
|
||||
localtm = _time.localtime(ts)
|
||||
|
|
|
@ -6212,6 +6212,10 @@ class ZoneInfoTest(unittest.TestCase):
|
|||
ts1 = dt.replace(fold=1).timestamp()
|
||||
self.assertEqual(ts0, s0 + ss / 2)
|
||||
self.assertEqual(ts1, s0 - ss / 2)
|
||||
# gh-83861
|
||||
utc0 = dt.astimezone(timezone.utc)
|
||||
utc1 = dt.replace(fold=1).astimezone(timezone.utc)
|
||||
self.assertEqual(utc0, utc1 + timedelta(0, ss))
|
||||
finally:
|
||||
if TZ is None:
|
||||
del os.environ['TZ']
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Fix datetime.astimezone method return value when invoked on a naive datetime
|
||||
instance that represents local time falling in a timezone transition gap.
|
||||
PEP 495 requires that instances with fold=1 produce earlier times than those
|
||||
with fold=0 in this case.
|
|
@ -6153,17 +6153,31 @@ local_to_seconds(int year, int month, int day,
|
|||
static PyObject *
|
||||
local_timezone_from_local(PyDateTime_DateTime *local_dt)
|
||||
{
|
||||
long long seconds;
|
||||
long long seconds, seconds2;
|
||||
time_t timestamp;
|
||||
int fold = DATE_GET_FOLD(local_dt);
|
||||
seconds = local_to_seconds(GET_YEAR(local_dt),
|
||||
GET_MONTH(local_dt),
|
||||
GET_DAY(local_dt),
|
||||
DATE_GET_HOUR(local_dt),
|
||||
DATE_GET_MINUTE(local_dt),
|
||||
DATE_GET_SECOND(local_dt),
|
||||
DATE_GET_FOLD(local_dt));
|
||||
fold);
|
||||
if (seconds == -1)
|
||||
return NULL;
|
||||
seconds2 = local_to_seconds(GET_YEAR(local_dt),
|
||||
GET_MONTH(local_dt),
|
||||
GET_DAY(local_dt),
|
||||
DATE_GET_HOUR(local_dt),
|
||||
DATE_GET_MINUTE(local_dt),
|
||||
DATE_GET_SECOND(local_dt),
|
||||
!fold);
|
||||
if (seconds2 == -1)
|
||||
return NULL;
|
||||
/* Detect gap */
|
||||
if (seconds2 != seconds && (seconds2 > seconds) == fold)
|
||||
seconds = seconds2;
|
||||
|
||||
/* XXX: add bounds check */
|
||||
timestamp = seconds - epoch;
|
||||
return local_timezone_from_timestamp(timestamp);
|
||||
|
|
Loading…
Reference in New Issue