[Python-checkins] cpython: #665194: Update email.utils.localtime to use astimezone, and fix bug.
r.david.murray
python-checkins at python.org
Thu Aug 23 03:34:29 CEST 2012
http://hg.python.org/cpython/rev/71b9cca81598
changeset: 78709:71b9cca81598
user: R David Murray <rdmurray at bitdance.com>
date: Wed Aug 22 21:34:00 2012 -0400
summary:
#665194: Update email.utils.localtime to use astimezone, and fix bug.
The new code correctly handles historic changes in UTC offsets.
A test for this should follow.
Original patch by Alexander Belopolsky.
files:
Lib/email/utils.py | 51 ++++++++----------
Lib/test/test_email/test_utils.py | 10 ++-
Misc/NEWS | 3 +
3 files changed, 33 insertions(+), 31 deletions(-)
diff --git a/Lib/email/utils.py b/Lib/email/utils.py
--- a/Lib/email/utils.py
+++ b/Lib/email/utils.py
@@ -386,33 +386,26 @@
"""
if dt is None:
- seconds = time.time()
- else:
- if dt.tzinfo is None:
- # A naive datetime is given. Convert to a (localtime)
- # timetuple and pass to system mktime together with
- # the isdst hint. System mktime will return seconds
- # sysce epoch.
- tm = dt.timetuple()[:-1] + (isdst,)
- seconds = time.mktime(tm)
+ dt = datetime.datetime.now(datetime.timezone.utc)
+ if dt.tzinfo is not None:
+ return dt.astimezone()
+ # We have a naive datetime. Convert to a (localtime) timetuple and pass to
+ # system mktime together with the isdst hint. System mktime will return
+ # seconds since epoch.
+ tm = dt.timetuple()[:-1] + (isdst,)
+ seconds = time.mktime(tm)
+ localtm = time.localtime(seconds)
+ try:
+ delta = datetime.timedelta(seconds=localtm.tm_gmtoff)
+ tz = datetime.timezone(delta, localtm.tm_zone)
+ except AttributeError:
+ # Compute UTC offset and compare with the value implied by tm_isdst.
+ # If the values match, use the zone name implied by tm_isdst.
+ delta = dt - datetime.datetime(*time.gmtime(ts)[:6])
+ dst = time.daylight and localtm.tm_isdst > 0
+ gmtoff = -(time.altzone if dst else time.timezone)
+ if delta == datetime.timedelta(seconds=gmtoff):
+ tz = datetime.timezone(delta, time.tzname[dst])
else:
- # An aware datetime is given. Use aware datetime
- # arithmetics to find seconds since epoch.
- delta = dt - datetime.datetime(1970, 1, 1,
- tzinfo=datetime.timezone.utc)
- seconds = delta.total_seconds()
- tm = time.localtime(seconds)
-
- # XXX: The following logic may not work correctly if UTC
- # offset has changed since time provided in dt. This will be
- # corrected in C implementation for platforms that support
- # tm_gmtoff.
- if time.daylight and tm.tm_isdst:
- offset = time.altzone
- tzname = time.tzname[1]
- else:
- offset = time.timezone
- tzname = time.tzname[0]
-
- tz = datetime.timezone(datetime.timedelta(seconds=-offset), tzname)
- return datetime.datetime.fromtimestamp(seconds, tz)
+ tz = datetime.timezone(delta)
+ return dt.replace(tzinfo=tz)
diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py
--- a/Lib/test/test_email/test_utils.py
+++ b/Lib/test/test_email/test_utils.py
@@ -87,17 +87,23 @@
t2 = utils.localtime(t1)
self.assertEqual(t1, t2)
+ @test.support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0')
def test_localtime_epoch_utc_daylight_true(self):
test.support.patch(self, time, 'daylight', True)
t0 = datetime.datetime(1970, 1, 1, tzinfo = datetime.timezone.utc)
t1 = utils.localtime(t0)
- self.assertEqual(t0, t1)
+ t2 = t0 - datetime.timedelta(hours=5)
+ t2 = t2.replace(tzinfo = datetime.timezone(datetime.timedelta(hours=-5)))
+ self.assertEqual(t1, t2)
+ @test.support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0')
def test_localtime_epoch_utc_daylight_false(self):
test.support.patch(self, time, 'daylight', False)
t0 = datetime.datetime(1970, 1, 1, tzinfo = datetime.timezone.utc)
t1 = utils.localtime(t0)
- self.assertEqual(t0, t1)
+ t2 = t0 - datetime.timedelta(hours=5)
+ t2 = t2.replace(tzinfo = datetime.timezone(datetime.timedelta(hours=-5)))
+ self.assertEqual(t1, t2)
def test_localtime_epoch_notz_daylight_true(self):
test.support.patch(self, time, 'daylight', True)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,9 @@
Library
-------
+- Issue ##665194: Update email.utils.localtime to use datetime.astimezone and
+ correctly handle historic changes in UTC offsets.
+
- Issue #15199: Fix JavaScript's default MIME type to application/javascript.
Patch by Bohuslav Kabrda.
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list