forked from orbit-oss/flask
Merge pull request #2374 from astralblue/json_encode_non_utc_datetimes
Correctly JSON-encode datetimes aware of non-UTC timezones
This commit is contained in:
commit
d625d41104
3 changed files with 35 additions and 1 deletions
2
CHANGES
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
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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…
Add table
Add a link
Reference in a new issue