Added a usegmt flag to email.Utils.formatdate - this allows it to be

used to replace rfc822.formatdate for protocols like HTTP (where 'GMT' must
be the timezone string).
This commit is contained in:
Anthony Baxter 2004-10-11 13:53:08 +00:00
parent 7f468f29f4
commit 3dd9e46161
5 changed files with 28 additions and 7 deletions

View file

@ -84,7 +84,7 @@ changes in daylight savings time, though not worth worrying about for
common use. common use.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{formatdate}{\optional{timeval\optional{, localtime}}} \begin{funcdesc}{formatdate}{\optional{timeval\optional{, localtime}\optional{, usegmt}}}
Returns a date string as per \rfc{2822}, e.g.: Returns a date string as per \rfc{2822}, e.g.:
\begin{verbatim} \begin{verbatim}
@ -99,6 +99,11 @@ Optional \var{localtime} is a flag that when \code{True}, interprets
\var{timeval}, and returns a date relative to the local timezone \var{timeval}, and returns a date relative to the local timezone
instead of UTC, properly taking daylight savings time into account. instead of UTC, properly taking daylight savings time into account.
The default is \code{False} meaning UTC is used. The default is \code{False} meaning UTC is used.
Optional \var{usegmt} is a flag that when \code{True}, outputs a
date string with the timezone as an ascii string \code{GMT}, rather
than a numeric \code{-0000}. This is needed for some protocols (such
as HTTP). This only applies when \var{localtime} is \code{False}
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{make_msgid}{\optional{idstring}} \begin{funcdesc}{make_msgid}{\optional{idstring}}

View file

@ -103,7 +103,7 @@ ecre = re.compile(r'''
def formatdate(timeval=None, localtime=False): def formatdate(timeval=None, localtime=False, usegmt=False):
"""Returns a date string as specified by RFC 2822, e.g.: """Returns a date string as specified by RFC 2822, e.g.:
Fri, 09 Nov 2001 01:08:47 -0000 Fri, 09 Nov 2001 01:08:47 -0000
@ -114,6 +114,10 @@ def formatdate(timeval=None, localtime=False):
Optional localtime is a flag that when True, interprets timeval, and Optional localtime is a flag that when True, interprets timeval, and
returns a date relative to the local timezone instead of UTC, properly returns a date relative to the local timezone instead of UTC, properly
taking daylight savings time into account. taking daylight savings time into account.
Optional argument usegmt means that the timezone is written out as
an ascii string, not numeric one (so "GMT" instead of "+0000"). This
is needed for HTTP, and is only used when localtime==False.
""" """
# Note: we cannot use strftime() because that honors the locale and RFC # Note: we cannot use strftime() because that honors the locale and RFC
# 2822 requires that day and month names be the English abbreviations. # 2822 requires that day and month names be the English abbreviations.
@ -138,6 +142,9 @@ def formatdate(timeval=None, localtime=False):
else: else:
now = time.gmtime(timeval) now = time.gmtime(timeval)
# Timezone offset is always -0000 # Timezone offset is always -0000
if usegmt:
zone = 'GMT'
else:
zone = '-0000' zone = '-0000'
return '%s, %02d %s %04d %02d:%02d:%02d %s' % ( return '%s, %02d %s %04d %02d:%02d:%02d %s' % (
['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][now[6]], ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][now[6]],

View file

@ -2037,6 +2037,15 @@ class TestMiscellaneous(unittest.TestCase):
Utils.parsedate(Utils.formatdate(now, localtime=True))[:6], Utils.parsedate(Utils.formatdate(now, localtime=True))[:6],
time.localtime(now)[:6]) time.localtime(now)[:6])
def test_formatdate_usegmt(self):
now = time.time()
self.assertEqual(
Utils.formatdate(now, localtime=False),
time.strftime('%a, %d %b %Y %H:%M:%S -0000', time.gmtime(now)))
self.assertEqual(
Utils.formatdate(now, localtime=False, usegmt=True),
time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(now)))
def test_parsedate_none(self): def test_parsedate_none(self):
self.assertEqual(Utils.parsedate(''), None) self.assertEqual(Utils.parsedate(''), None)

View file

@ -410,7 +410,7 @@ class URLopener:
def open_local_file(self, url): def open_local_file(self, url):
"""Use local file.""" """Use local file."""
import mimetypes, mimetools, rfc822, StringIO import mimetypes, mimetools, email.Utils, StringIO
host, file = splithost(url) host, file = splithost(url)
localname = url2pathname(file) localname = url2pathname(file)
try: try:
@ -418,7 +418,7 @@ class URLopener:
except OSError, e: except OSError, e:
raise IOError(e.errno, e.strerror, e.filename) raise IOError(e.errno, e.strerror, e.filename)
size = stats.st_size size = stats.st_size
modified = rfc822.formatdate(stats.st_mtime) modified = email.Utils.formatdate(stats.st_mtime, usegmt=True)
mtype = mimetypes.guess_type(url)[0] mtype = mimetypes.guess_type(url)[0]
headers = mimetools.Message(StringIO.StringIO( headers = mimetools.Message(StringIO.StringIO(
'Content-Type: %s\nContent-Length: %d\nLast-modified: %s\n' % 'Content-Type: %s\nContent-Length: %d\nLast-modified: %s\n' %

View file

@ -99,7 +99,6 @@ import os
import posixpath import posixpath
import random import random
import re import re
import rfc822
import sha import sha
import socket import socket
import sys import sys
@ -1129,12 +1128,13 @@ class FileHandler(BaseHandler):
# not entirely sure what the rules are here # not entirely sure what the rules are here
def open_local_file(self, req): def open_local_file(self, req):
import email.Utils
host = req.get_host() host = req.get_host()
file = req.get_selector() file = req.get_selector()
localfile = url2pathname(file) localfile = url2pathname(file)
stats = os.stat(localfile) stats = os.stat(localfile)
size = stats.st_size size = stats.st_size
modified = rfc822.formatdate(stats.st_mtime) modified = email.Utils.formatdate(stats.st_mtime, usegmt=True)
mtype = mimetypes.guess_type(file)[0] mtype = mimetypes.guess_type(file)[0]
headers = mimetools.Message(StringIO( headers = mimetools.Message(StringIO(
'Content-type: %s\nContent-length: %d\nLast-modified: %s\n' % 'Content-type: %s\nContent-length: %d\nLast-modified: %s\n' %