Skip to content

Commit 5e6661b

Browse files
gh-72346: Added isdst deprecation warning to email.utils.localtime (GH-91450)
1 parent 40d4f15 commit 5e6661b

File tree

5 files changed

+34
-45
lines changed

5 files changed

+34
-45
lines changed

Doc/library/email.utils.rst

+10-12
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,17 @@ module:
1313

1414
.. function:: localtime(dt=None)
1515

16-
Return local time as an aware datetime object. If called without
17-
arguments, return current time. Otherwise *dt* argument should be a
18-
:class:`~datetime.datetime` instance, and it is converted to the local time
19-
zone according to the system time zone database. If *dt* is naive (that
20-
is, ``dt.tzinfo`` is ``None``), it is assumed to be in local time. In this
21-
case, a positive or zero value for *isdst* causes ``localtime`` to presume
22-
initially that summer time (for example, Daylight Saving Time) is or is not
23-
(respectively) in effect for the specified time. A negative value for
24-
*isdst* causes the ``localtime`` to attempt to divine whether summer time
25-
is in effect for the specified time.
26-
27-
.. versionadded:: 3.3
16+
Return local time as an aware datetime object. If called without
17+
arguments, return current time. Otherwise *dt* argument should be a
18+
:class:`~datetime.datetime` instance, and it is converted to the local time
19+
zone according to the system time zone database. If *dt* is naive (that
20+
is, ``dt.tzinfo`` is ``None``), it is assumed to be in local time. The
21+
*isdst* parameter is ignored.
2822

23+
.. versionadded:: 3.3
24+
25+
.. deprecated-removed:: 3.12 3.14
26+
The *isdst* parameter.
2927

3028
.. function:: make_msgid(idstring=None, domain=None)
3129

Doc/whatsnew/3.12.rst

+3
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,9 @@ Pending Removal in Python 3.14
565565
* Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
566566
bases using the C API.
567567

568+
* Deprecated the *isdst* parameter in :func:`email.utils.localtime`.
569+
(Contributed by Alan Williams in :gh:`72346`.)
570+
568571
* ``__package__`` and ``__cached__`` will cease to be set or taken
569572
into consideration by the import system (:gh:`97879`).
570573

Lib/email/utils.py

+11-29
Original file line numberDiff line numberDiff line change
@@ -331,41 +331,23 @@ def collapse_rfc2231_value(value, errors='replace',
331331
# better than not having it.
332332
#
333333

334-
def localtime(dt=None, isdst=-1):
334+
def localtime(dt=None, isdst=None):
335335
"""Return local time as an aware datetime object.
336336
337337
If called without arguments, return current time. Otherwise *dt*
338338
argument should be a datetime instance, and it is converted to the
339339
local time zone according to the system time zone database. If *dt* is
340340
naive (that is, dt.tzinfo is None), it is assumed to be in local time.
341-
In this case, a positive or zero value for *isdst* causes localtime to
342-
presume initially that summer time (for example, Daylight Saving Time)
343-
is or is not (respectively) in effect for the specified time. A
344-
negative value for *isdst* causes the localtime() function to attempt
345-
to divine whether summer time is in effect for the specified time.
341+
The isdst parameter is ignored.
346342
347343
"""
344+
if isdst is not None:
345+
import warnings
346+
warnings._deprecated(
347+
"The 'isdst' parameter to 'localtime'",
348+
message='{name} is deprecated and slated for removal in Python {remove}',
349+
remove=(3, 14),
350+
)
348351
if dt is None:
349-
return datetime.datetime.now(datetime.timezone.utc).astimezone()
350-
if dt.tzinfo is not None:
351-
return dt.astimezone()
352-
# We have a naive datetime. Convert to a (localtime) timetuple and pass to
353-
# system mktime together with the isdst hint. System mktime will return
354-
# seconds since epoch.
355-
tm = dt.timetuple()[:-1] + (isdst,)
356-
seconds = time.mktime(tm)
357-
localtm = time.localtime(seconds)
358-
try:
359-
delta = datetime.timedelta(seconds=localtm.tm_gmtoff)
360-
tz = datetime.timezone(delta, localtm.tm_zone)
361-
except AttributeError:
362-
# Compute UTC offset and compare with the value implied by tm_isdst.
363-
# If the values match, use the zone name implied by tm_isdst.
364-
delta = dt - datetime.datetime(*time.gmtime(seconds)[:6])
365-
dst = time.daylight and localtm.tm_isdst > 0
366-
gmtoff = -(time.altzone if dst else time.timezone)
367-
if delta == datetime.timedelta(seconds=gmtoff):
368-
tz = datetime.timezone(delta, time.tzname[dst])
369-
else:
370-
tz = datetime.timezone(delta)
371-
return dt.replace(tzinfo=tz)
352+
dt = datetime.datetime.now()
353+
return dt.astimezone()

Lib/test/test_email/test_utils.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -83,30 +83,30 @@ def test_localtime_is_tz_aware_daylight_false(self):
8383
def test_localtime_daylight_true_dst_false(self):
8484
test.support.patch(self, time, 'daylight', True)
8585
t0 = datetime.datetime(2012, 3, 12, 1, 1)
86-
t1 = utils.localtime(t0, isdst=-1)
86+
t1 = utils.localtime(t0)
8787
t2 = utils.localtime(t1)
8888
self.assertEqual(t1, t2)
8989

9090
def test_localtime_daylight_false_dst_false(self):
9191
test.support.patch(self, time, 'daylight', False)
9292
t0 = datetime.datetime(2012, 3, 12, 1, 1)
93-
t1 = utils.localtime(t0, isdst=-1)
93+
t1 = utils.localtime(t0)
9494
t2 = utils.localtime(t1)
9595
self.assertEqual(t1, t2)
9696

9797
@test.support.run_with_tz('Europe/Minsk')
9898
def test_localtime_daylight_true_dst_true(self):
9999
test.support.patch(self, time, 'daylight', True)
100100
t0 = datetime.datetime(2012, 3, 12, 1, 1)
101-
t1 = utils.localtime(t0, isdst=1)
101+
t1 = utils.localtime(t0)
102102
t2 = utils.localtime(t1)
103103
self.assertEqual(t1, t2)
104104

105105
@test.support.run_with_tz('Europe/Minsk')
106106
def test_localtime_daylight_false_dst_true(self):
107107
test.support.patch(self, time, 'daylight', False)
108108
t0 = datetime.datetime(2012, 3, 12, 1, 1)
109-
t1 = utils.localtime(t0, isdst=1)
109+
t1 = utils.localtime(t0)
110110
t2 = utils.localtime(t1)
111111
self.assertEqual(t1, t2)
112112

@@ -157,6 +157,11 @@ def test_variable_tzname(self):
157157
t1 = utils.localtime(t0)
158158
self.assertEqual(t1.tzname(), 'EET')
159159

160+
def test_isdst_deprecation(self):
161+
with self.assertWarns(DeprecationWarning):
162+
t0 = datetime.datetime(1990, 1, 1)
163+
t1 = utils.localtime(t0, isdst=True)
164+
160165
# Issue #24836: The timezone files are out of date (pre 2011k)
161166
# on Mac OS X Snow Leopard.
162167
@test.support.requires_mac_ver(10, 7)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added deprecation warning to *isdst* parameter of :func:`email.utils.localtime`.

0 commit comments

Comments
 (0)