Browse Source

Merge pull request #2374 from astralblue/json_encode_non_utc_datetimes

Correctly JSON-encode datetimes aware of non-UTC timezones
pull/2381/head
David Lord 7 years ago committed by GitHub
parent
commit
d625d41104
  1. 2
      CHANGES
  2. 4
      flask/json/__init__.py
  3. 30
      tests/test_helpers.py

2
CHANGES

@ -79,6 +79,7 @@ Major release, unreleased
- Removed error handler caching because it caused unexpected results for some - Removed error handler caching because it caused unexpected results for some
exception inheritance hierarchies. Register handlers explicitly for each exception inheritance hierarchies. Register handlers explicitly for each
exception if you don't want to traverse the MRO. (`#2362`_) exception if you don't want to traverse the MRO. (`#2362`_)
- Fix incorrect JSON encoding of aware, non-UTC datetimes. (`#2374`_)
- Template auto reloading will honor the ``run`` command's ``debug`` flag even - Template auto reloading will honor the ``run`` command's ``debug`` flag even
if ``app.jinja_env`` was already accessed. (`#2373`_) if ``app.jinja_env`` was already accessed. (`#2373`_)
@ -104,6 +105,7 @@ Major release, unreleased
.. _#2354: https://github.com/pallets/flask/pull/2354 .. _#2354: https://github.com/pallets/flask/pull/2354
.. _#2358: https://github.com/pallets/flask/pull/2358 .. _#2358: https://github.com/pallets/flask/pull/2358
.. _#2362: https://github.com/pallets/flask/pull/2362 .. _#2362: https://github.com/pallets/flask/pull/2362
.. _#2374: https://github.com/pallets/flask/pull/2374
.. _#2373: https://github.com/pallets/flask/pull/2373 .. _#2373: https://github.com/pallets/flask/pull/2373
Version 0.12.2 Version 0.12.2

4
flask/json/__init__.py

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import io import io
import uuid import uuid
from datetime import date from datetime import date, datetime
from flask.globals import current_app, request from flask.globals import current_app, request
from flask._compat import text_type, PY2 from flask._compat import text_type, PY2
@ -62,6 +62,8 @@ class JSONEncoder(_json.JSONEncoder):
return list(iterable) return list(iterable)
return JSONEncoder.default(self, o) return JSONEncoder.default(self, o)
""" """
if isinstance(o, datetime):
return http_date(o.utctimetuple())
if isinstance(o, date): if isinstance(o, date):
return http_date(o.timetuple()) return http_date(o.timetuple())
if isinstance(o, uuid.UUID): if isinstance(o, uuid.UUID):

30
tests/test_helpers.py

@ -34,6 +34,27 @@ def has_encoding(name):
return False return False
class FixedOffset(datetime.tzinfo):
"""Fixed offset in hours east from UTC.
This is a slight adaptation of the ``FixedOffset`` example found in
https://docs.python.org/2.7/library/datetime.html.
"""
def __init__(self, hours, name):
self.__offset = datetime.timedelta(hours=hours)
self.__name = name
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return datetime.timedelta()
class TestJSON(object): class TestJSON(object):
def test_ignore_cached_json(self, app): def test_ignore_cached_json(self, app):
with app.test_request_context('/', method='POST', data='malformed', with app.test_request_context('/', method='POST', data='malformed',
@ -177,6 +198,15 @@ class TestJSON(object):
assert rv.mimetype == 'application/json' assert rv.mimetype == 'application/json'
assert flask.json.loads(rv.data)['x'] == http_date(d.timetuple()) assert flask.json.loads(rv.data)['x'] == http_date(d.timetuple())
@pytest.mark.parametrize('tz', (('UTC', 0), ('PST', -8), ('KST', 9)))
def test_jsonify_aware_datetimes(self, tz):
"""Test if aware datetime.datetime objects are converted into GMT."""
tzinfo = FixedOffset(hours=tz[1], name=tz[0])
dt = datetime.datetime(2017, 1, 1, 12, 34, 56, tzinfo=tzinfo)
gmt = FixedOffset(hours=0, name='GMT')
expected = dt.astimezone(gmt).strftime('"%a, %d %b %Y %H:%M:%S %Z"')
assert flask.json.JSONEncoder().encode(dt) == expected
def test_jsonify_uuid_types(self, app, client): def test_jsonify_uuid_types(self, app, client):
"""Test jsonify with uuid.UUID types""" """Test jsonify with uuid.UUID types"""

Loading…
Cancel
Save