Issue #22932: Fix timezones in email.utils.formatdate.

Patch from Dmitry Shachnev.
diff --git a/Lib/email/utils.py b/Lib/email/utils.py
index 317fdfa..5080d81 100644
--- a/Lib/email/utils.py
+++ b/Lib/email/utils.py
@@ -155,30 +155,14 @@
     # 2822 requires that day and month names be the English abbreviations.
     if timeval is None:
         timeval = time.time()
-    if localtime:
-        now = time.localtime(timeval)
-        # Calculate timezone offset, based on whether the local zone has
-        # daylight savings time, and whether DST is in effect.
-        if time.daylight and now[-1]:
-            offset = time.altzone
-        else:
-            offset = time.timezone
-        hours, minutes = divmod(abs(offset), 3600)
-        # Remember offset is in seconds west of UTC, but the timezone is in
-        # minutes east of UTC, so the signs differ.
-        if offset > 0:
-            sign = '-'
-        else:
-            sign = '+'
-        zone = '%s%02d%02d' % (sign, hours, minutes // 60)
+    if localtime or usegmt:
+        dt = datetime.datetime.fromtimestamp(timeval, datetime.timezone.utc)
     else:
-        now = time.gmtime(timeval)
-        # Timezone offset is always -0000
-        if usegmt:
-            zone = 'GMT'
-        else:
-            zone = '-0000'
-    return _format_timetuple_and_zone(now, zone)
+        dt = datetime.datetime.utcfromtimestamp(timeval)
+    if localtime:
+        dt = dt.astimezone()
+        usegmt = False
+    return format_datetime(dt, usegmt)
 
 def format_datetime(dt, usegmt=False):
     """Turn a datetime into a date string as specified in RFC 2822.
diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py
index 4abdc04..1e9cd63 100644
--- a/Lib/test/test_email/test_utils.py
+++ b/Lib/test/test_email/test_utils.py
@@ -136,5 +136,25 @@
         t1 = utils.localtime(t0)
         self.assertEqual(t1.tzname(), 'EET')
 
+class FormatDateTests(unittest.TestCase):
+
+    @test.support.run_with_tz('Europe/Minsk')
+    def test_formatdate(self):
+        timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0))
+        string = utils.formatdate(timeval, localtime=False, usegmt=False)
+        self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 -0000')
+        string = utils.formatdate(timeval, localtime=False, usegmt=True)
+        self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 GMT')
+
+    @test.support.run_with_tz('Europe/Minsk')
+    def test_formatdate_with_localtime(self):
+        timeval = time.mktime((2011, 1, 1, 18, 0, 0, 6, 1, 0))
+        string = utils.formatdate(timeval, localtime=True)
+        self.assertEqual(string, 'Sat, 01 Jan 2011 18:00:00 +0200')
+        # Minsk moved from +0200 (with DST) to +0300 (without DST) in 2011
+        timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0))
+        string = utils.formatdate(timeval, localtime=True)
+        self.assertEqual(string, 'Thu, 01 Dec 2011 18:00:00 +0300')
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/ACKS b/Misc/ACKS
index de33df1..cc557b3 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1247,6 +1247,7 @@
 Pete Sevander
 Denis Severson
 Ian Seyer
+Dmitry Shachnev
 Daniel Shahaf
 Ha Shao
 Mark Shannon
diff --git a/Misc/NEWS b/Misc/NEWS
index 6798182..1aa2ea3 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -66,6 +66,9 @@
 Library
 -------
 
+- Issue #22932: Fix timezones in email.utils.formatdate.
+  Patch from Dmitry Shachnev.
+
 - Issue #23779: imaplib raises TypeError if authenticator tries to abort.
   Patch from Craig Holmquist.