Skip to content

Commit

Permalink
fix date formatting for non-English locales
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangyoufu authored and defnull committed Dec 19, 2019
1 parent 8e898e4 commit 9f81b80
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 19 deletions.
28 changes: 15 additions & 13 deletions bottle.py
Expand Up @@ -69,8 +69,8 @@ def _cli_patch(cli_args): # pragma: no coverage
###############################################################################


import base64, cgi, email.utils, functools, hmac, imp, itertools, mimetypes,\
os, re, tempfile, threading, time, warnings, weakref, hashlib
import base64, calendar, cgi, email.utils, functools, hmac, imp, itertools,\
mimetypes, os, re, tempfile, threading, time, warnings, weakref, hashlib

from types import FunctionType
from datetime import date as datedate, datetime, timedelta
Expand Down Expand Up @@ -1887,11 +1887,7 @@ def set_cookie(self, name, value, secret=None, digestmod=hashlib.sha256, **optio
if isinstance(value, timedelta):
value = value.seconds + value.days * 24 * 3600
if key == 'expires':
if isinstance(value, (datedate, datetime)):
value = value.timetuple()
elif isinstance(value, (int, float)):
value = time.gmtime(value)
value = time.strftime("%a, %d %b %Y %H:%M:%S GMT", value)
value = http_date(value)
if key in ('same_site', 'samesite'): # 'samesite' variant added in 0.13
key, value = 'samesite', (value or "none").lower()
if value not in ('lax', 'strict', 'none'):
Expand Down Expand Up @@ -2965,13 +2961,19 @@ def debug(mode=True):


def http_date(value):
if isinstance(value, (datedate, datetime)):
if isinstance(value, basestring):
return value
if isinstance(value, datetime):
# aware datetime.datetime is converted to UTC time
# naive datetime.datetime is treated as UTC time
value = value.utctimetuple()
elif isinstance(value, (int, float)):
value = time.gmtime(value)
if not isinstance(value, basestring):
value = time.strftime("%a, %d %b %Y %H:%M:%S GMT", value)
return value
elif isinstance(value, datedate):
# datetime.date is naive, and is treated as UTC time
value = value.timetuple()
if not isinstance(value, (int, float)):
# convert struct_time in UTC to UNIX timestamp
value = calendar.timegm(value)
return email.utils.formatdate(value, usegmt=True)


def parse_date(ims):
Expand Down
18 changes: 12 additions & 6 deletions test/test_sendfile.py
Expand Up @@ -13,23 +13,29 @@
root2 = os.path.dirname(bottle.__file__)


weekday_full = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
weekday_abbr = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
month_abbr = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

class TestDateParser(unittest.TestCase):
def test_rfc1123(self):
"""DateParser: RFC 1123 format"""
ts = time.time()
rs = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(ts))
rs = bottle.http_date(ts)
self.assertEqual(int(ts), int(parse_date(rs)))

def test_rfc850(self):
"""DateParser: RFC 850 format"""
ts = time.time()
rs = time.strftime("%A, %d-%b-%y %H:%M:%S GMT", time.gmtime(ts))
t = time.gmtime(ts)
rs = time.strftime("%%s, %d-%%s-%y %H:%M:%S GMT", t) % (weekday_full[t.tm_wday], month_abbr[t.tm_mon])
self.assertEqual(int(ts), int(parse_date(rs)))

def test_asctime(self):
"""DateParser: asctime format"""
ts = time.time()
rs = time.strftime("%a %b %d %H:%M:%S %Y", time.gmtime(ts))
t = time.gmtime(ts)
rs = time.strftime("%%s %%s %d %H:%M:%S %Y", t) % (weekday_abbr[t.tm_wday], month_abbr[t.tm_mon])
self.assertEqual(int(ts), int(parse_date(rs)))

def test_bad(self):
Expand Down Expand Up @@ -81,12 +87,12 @@ def test_mime(self):

def test_ims(self):
""" SendFile: If-Modified-Since"""
request.environ['HTTP_IF_MODIFIED_SINCE'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime())
request.environ['HTTP_IF_MODIFIED_SINCE'] = bottle.http_date(time.time())
res = static_file(basename, root=root)
self.assertEqual(304, res.status_code)
self.assertEqual(int(os.stat(__file__).st_mtime), parse_date(res.headers['Last-Modified']))
self.assertAlmostEqual(int(time.time()), parse_date(res.headers['Date']))
request.environ['HTTP_IF_MODIFIED_SINCE'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(100))
request.environ['HTTP_IF_MODIFIED_SINCE'] = bottle.http_date(100)
self.assertEqual(open(__file__,'rb').read(), static_file(basename, root=root).body.read())

def test_etag(self):
Expand Down Expand Up @@ -116,7 +122,7 @@ def test_download(self):

f = static_file(basename, root=root, download=True)
self.assertEqual('attachment; filename="%s"' % basename, f.headers['Content-Disposition'])
request.environ['HTTP_IF_MODIFIED_SINCE'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(100))
request.environ['HTTP_IF_MODIFIED_SINCE'] = bottle.http_date(100)

f = static_file(basename, root=root)
self.assertEqual(open(__file__,'rb').read(), f.body.read())
Expand Down

0 comments on commit 9f81b80

Please sign in to comment.