[Python-checkins] cpython: Issues #11024: Fixes and additional tests for Time2Internaldate.

alexander.belopolsky python-checkins at python.org
Sat Jun 23 03:11:01 CEST 2012


http://hg.python.org/cpython/rev/42b9d9d795f7
changeset:   77603:42b9d9d795f7
user:        Alexander Belopolsky <alexander.belopolsky at gmail.com>
date:        Fri Jun 22 21:03:39 2012 -0400
summary:
  Issues #11024: Fixes and additional tests for Time2Internaldate.

files:
  Doc/library/imaplib.rst  |  16 +++++----
  Lib/imaplib.py           |  45 ++++++++++++++++-----------
  Lib/test/test_imaplib.py |  34 +++++++++++++++-----
  Misc/NEWS                |   2 +
  4 files changed, 62 insertions(+), 35 deletions(-)


diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst
--- a/Doc/library/imaplib.rst
+++ b/Doc/library/imaplib.rst
@@ -113,13 +113,15 @@
 
 .. function:: Time2Internaldate(date_time)
 
-   Convert *date_time* to an IMAP4 ``INTERNALDATE`` representation.  The
-   return value is a string in the form: ``"DD-Mmm-YYYY HH:MM:SS
-   +HHMM"`` (including double-quotes).  The *date_time* argument can be a
-   number (int or float) representing seconds since epoch (as returned
-   by :func:`time.time`), a 9-tuple representing local time (as returned by
-   :func:`time.localtime`), or a double-quoted string.  In the last case, it
-   is assumed to already be in the correct format.
+   Convert *date_time* to an IMAP4 ``INTERNALDATE`` representation.
+   The return value is a string in the form: ``"DD-Mmm-YYYY HH:MM:SS
+   +HHMM"`` (including double-quotes).  The *date_time* argument can
+   be a number (int or float) representing seconds since epoch (as
+   returned by :func:`time.time`), a 9-tuple representing local time
+   an instance of :class:`time.struct_time` (as returned by
+   :func:`time.localtime`), an aware instance of
+   :class:`datetime.datetime`, or a double-quoted string.  In the last
+   case, it is assumed to already be in the correct format.
 
 Note that IMAP4 message numbers change as the mailbox changes; in particular,
 after an ``EXPUNGE`` command performs deletions the remaining messages are
diff --git a/Lib/imaplib.py b/Lib/imaplib.py
--- a/Lib/imaplib.py
+++ b/Lib/imaplib.py
@@ -23,7 +23,7 @@
 __version__ = "2.58"
 
 import binascii, errno, random, re, socket, subprocess, sys, time, calendar
-
+from datetime import datetime, timezone, timedelta
 try:
     import ssl
     HAVE_SSL = True
@@ -1313,10 +1313,8 @@
             return ''
         return binascii.a2b_base64(inp)
 
-
-
-Mon2num = {b'Jan': 1, b'Feb': 2, b'Mar': 3, b'Apr': 4, b'May': 5, b'Jun': 6,
-           b'Jul': 7, b'Aug': 8, b'Sep': 9, b'Oct': 10, b'Nov': 11, b'Dec': 12}
+Months = ' Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' ')
+Mon2num = {s.encode():n+1 for n, s in enumerate(Months[1:])}
 
 def Internaldate2tuple(resp):
     """Parse an IMAP4 INTERNALDATE string.
@@ -1384,28 +1382,37 @@
     Return string in form: '"DD-Mmm-YYYY HH:MM:SS +HHMM"'.  The
     date_time argument can be a number (int or float) representing
     seconds since epoch (as returned by time.time()), a 9-tuple
-    representing local time (as returned by time.localtime()), or a
+    representing local time, an instance of time.struct_time (as
+    returned by time.localtime()), an aware datetime instance or a
     double-quoted string.  In the last case, it is assumed to already
     be in the correct format.
     """
-
     if isinstance(date_time, (int, float)):
-        tt = time.localtime(date_time)
-    elif isinstance(date_time, (tuple, time.struct_time)):
-        tt = date_time
+        dt = datetime.fromtimestamp(date_time,
+                                    timezone.utc).astimezone()
+    elif isinstance(date_time, tuple):
+        try:
+            gmtoff = date_time.tm_gmtoff
+        except AttributeError:
+            if time.daylight:
+                dst = date_time[8]
+                if dst == -1:
+                    dst = time.localtime(time.mktime(date_time))[8]
+                gmtoff = -(time.timezone, time.altzone)[dst]
+            else:
+                gmtoff = -time.timezone
+        delta = timedelta(seconds=gmtoff)
+        dt = datetime(*date_time[:6], tzinfo=timezone(delta))
+    elif isinstance(date_time, datetime):
+        if date_time.tzinfo is None:
+            raise ValueError("date_time must be aware")
+        dt = date_time
     elif isinstance(date_time, str) and (date_time[0],date_time[-1]) == ('"','"'):
         return date_time        # Assume in correct format
     else:
         raise ValueError("date_time not of a known type")
-
-    dt = time.strftime("%d-%b-%Y %H:%M:%S", tt)
-    if dt[0] == '0':
-        dt = ' ' + dt[1:]
-    if time.daylight and tt[-1]:
-        zone = -time.altzone
-    else:
-        zone = -time.timezone
-    return '"' + dt + " %+03d%02d" % divmod(zone//60, 60) + '"'
+    fmt = '"%d-{}-%Y %H:%M:%S %z"'.format(Months[dt.month])
+    return dt.strftime(fmt)
 
 
 
diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py
--- a/Lib/test/test_imaplib.py
+++ b/Lib/test/test_imaplib.py
@@ -11,9 +11,9 @@
 import time
 import calendar
 
-from test.support import reap_threads, verbose, transient_internet, run_with_tz
+from test.support import reap_threads, verbose, transient_internet, run_with_tz, run_with_locale
 import unittest
-
+from datetime import datetime, timezone, timedelta
 try:
     import ssl
 except ImportError:
@@ -43,14 +43,30 @@
                             imaplib.Internaldate2tuple(
             b'25 (INTERNALDATE "02-Apr-2000 03:30:00 +0000")'))
 
+
+
+    def timevalues(self):
+        return [2000000000, 2000000000.0, time.localtime(2000000000),
+                (2033, 5, 18, 5, 33, 20, -1, -1, -1),
+                (2033, 5, 18, 5, 33, 20, -1, -1, 1),
+                datetime.fromtimestamp(2000000000, 
+                                       timezone(timedelta(0, 2*60*60))),
+                '"18-May-2033 05:33:20 +0200"']
+
+    @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
+    @run_with_tz('STD-1DST')
+    def test_Time2Internaldate(self):
+        expected = '"18-May-2033 05:33:20 +0200"'
+
+        for t in self.timevalues():
+            internal = imaplib.Time2Internaldate(t)
+            self.assertEqual(internal, expected)
+
     def test_that_Time2Internaldate_returns_a_result(self):
-        # We can check only that it successfully produces a result,
-        # not the correctness of the result itself, since the result
-        # depends on the timezone the machine is in.
-        timevalues = [2000000000, 2000000000.0, time.localtime(2000000000),
-                      '"18-May-2033 05:33:20 +0200"']
-
-        for t in timevalues:
+        # Without tzset, we can check only that it successfully
+        # produces a result, not the correctness of the result itself,
+        # since the result depends on the timezone the machine is in.
+        for t in self.timevalues():
             imaplib.Time2Internaldate(t)
 
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -40,6 +40,8 @@
 Library
 -------
 
+- Issues #11024: Fixes and additional tests for Time2Internaldate.
+
 - Issue #14626: Large refactoring of functions / parameters in the os module.
   Many functions now support "dir_fd" and "follow_symlinks" parameters;
   some also support accepting an open file descriptor in place of of a path

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list