我想使用JSON在Python中以序列化的形式发送datetime.datetime对象,并在JavaScript中使用JSON进行反序列化。如何最好地实现这一点?
我想使用JSON在Python中以序列化的形式发送datetime.datetime对象,并在JavaScript中使用JSON进行反序列化。如何最好地实现这一点?
date_handler = lambda obj: (
obj.isoformat()
if isinstance(obj, (datetime.datetime, datetime.date))
else None
)
json.dumps(datetime.datetime.now(), default=date_handler)
'"2010-04-20T20:08:21.634121"'
日期格式为ISO 8601格式。
一个更全面的默认处理程序函数:
def handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
elif isinstance(obj, ...):
return ...
else:
raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))
更新:还添加了类型和值的输出。
更新:还处理了日期。
isoformat()
方法无法提供这个功能。因此,在返回字符串之前,您应该确保将该信息附加到字符串中。 - Nicholas Franceschinadthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime) else json.JSONEncoder().default(obj)
。” - Pascal Bourqueor
替换为 if isinstance(obj, (datetime.datetime, datetime.date))
即可。这样做不会改变原有意思,但能让代码更加易懂。 - hobs 1985-04-12T23:20:50.52Z
json.dump(datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ'))
datetime
模块中具有本地支持:datetime.isoformat()
同时,在 simplejson
中也同样支持将datetime
对象默认转换成isoformat
字符串进行导出。无需手动使用strftime
函数调整格式。 - jrkdatetime
对象转换为isoformat
字符串。 对于我来说,simplejson.dumps(datetime.now())
会产生TypeError: datetime.datetime(...)不可JSON序列化
的错误。 - kostmojson.dumps(datetime.datetime.now().isoformat())
是魔法发生的地方。 - jathanismZ
代表格林威治时间(GMT/UTC)的军事无线电密码,也叫做祖鲁时间:http://zh.wikipedia.org/wiki/%E5%86%9B%E4%B8%9A%E6%97%B6%E9%97%B4%E5%8C%BA - Daniel J. Pritchettdatetime.datetime(2011, 5, 25, 13, 34, 5, 787000)
import json
json.dumps(d.isoformat())
'"2011-05-25T13:34:05.787000"'
var d = new Date("2011-05-25T13:34:05.787000");
d.toJSON()
'2011-05-25T20:34:05.787Z'
datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ')
datetime.datetime(2011, 5, 25, 20, 34, 5, 787000)
使用json
,您可以子类化JSONEncoder并覆盖default()方法,以提供自己的自定义序列化器:
import json
import datetime
class DateTimeJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
else:
return super(DateTimeJSONEncoder, self).default(obj)
然后,你可以这样调用它:
>>> DateTimeJSONEncoder().encode([datetime.datetime.now()])
'["2010-06-15T14:42:28"]'
obj.isoformat()
。您还可以使用更常见的 dumps()
调用,它接受其他有用的参数(例如indent
): simplejson.dumps(myobj, cls=JSONEncoder, ...) - rcoupdate = datetime.datetime.now()
>>> json = dumps(dict(foo='bar', innerdict=dict(date=date)))
>>> json
'{"innerdict": {"date": "2010-07-15T13:16:38.365579"}, "foo": "bar"}'
>>> loads(json)
{u'innerdict': {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)},
u'foo': u'bar'}
>>> json = dumps(['foo', 'bar', dict(date=date)])
>>> json
'["foo", "bar", {"date": "2010-07-15T13:16:38.365579"}]'
>>> loads(json)
[u'foo', u'bar', {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)}]
>>> json = dumps(['foo', 'bar', date])
>>> json
'["foo", "bar", "2010-07-15T13:16:38.365579"]'
>>> loads(json)
[u'foo', u'bar', u'2010-07-15T13:16:38.365579']
__all__ = ['dumps', 'loads']
import datetime
try:
import json
except ImportError:
import simplejson as json
class JSONDateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.date, datetime.datetime)):
return obj.isoformat()
else:
return json.JSONEncoder.default(self, obj)
def datetime_decoder(d):
if isinstance(d, list):
pairs = enumerate(d)
elif isinstance(d, dict):
pairs = d.items()
result = []
for k,v in pairs:
if isinstance(v, basestring):
try:
# The %f format code is only supported in Python >= 2.6.
# For Python <= 2.5 strip off microseconds
# v = datetime.datetime.strptime(v.rsplit('.', 1)[0],
# '%Y-%m-%dT%H:%M:%S')
v = datetime.datetime.strptime(v, '%Y-%m-%dT%H:%M:%S.%f')
except ValueError:
try:
v = datetime.datetime.strptime(v, '%Y-%m-%d').date()
except ValueError:
pass
elif isinstance(v, (dict, list)):
v = datetime_decoder(v)
result.append((k, v))
if isinstance(d, list):
return [x[1] for x in result]
elif isinstance(d, dict):
return dict(result)
def dumps(obj):
return json.dumps(obj, cls=JSONDateTimeEncoder)
def loads(obj):
return json.loads(obj, object_hook=datetime_decoder)
if __name__ == '__main__':
mytimestamp = datetime.datetime.utcnow()
mydate = datetime.date.today()
data = dict(
foo = 42,
bar = [mytimestamp, mydate],
date = mydate,
timestamp = mytimestamp,
struct = dict(
date2 = mydate,
timestamp2 = mytimestamp
)
)
print repr(data)
jsonstring = dumps(data)
print jsonstring
print repr(loads(jsonstring))
datetime.datetime.utcnow().isoformat()[:-3]+"Z"
,它将与 JavaScript 中的 JSON.stringify() 生成的完全相同。 - w00timport datetime
date = datetime.datetime.today()
json = '{"mydate":new Date("%s")}' % date.ctime()
.ctime()
不是一个很好的传递时间信息的方式,.isoformat()
更好。.ctime()
会像时区和夏令时不存在一样舍弃这些信息。 这个函数应该被废除。 - Evgenyimport json
import datetime
json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)
json.dumps({'created':datetime.datetime.now()})
None
。你可能希望改为抛出异常。 - Blender除了时间戳,我没有其他要补充社区维基的回答!
Javascript使用以下格式:
new Date().toJSON() // "2016-01-08T19:00:00.123Z"
Python 方面(对于json.dumps
处理程序,请参见其他答案):
>>> from datetime import datetime
>>> d = datetime.strptime('2016-01-08T19:00:00.123Z', '%Y-%m-%dT%H:%M:%S.%fZ')
>>> d
datetime.datetime(2016, 1, 8, 19, 0, 0, 123000)
>>> d.isoformat() + 'Z'
'2016-01-08T19:00:00.123000Z'
如果你省略掉那个 Z,就会导致像 Angular 这样的前端框架无法在浏览器本地时区中显示日期:
> $filter('date')('2016-01-08T19:00:00.123000Z', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 20:00:00"
> $filter('date')('2016-01-08T19:00:00.123000', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 19:00:00"
在Python端:
import time, json
from datetime import datetime as dt
your_date = dt.now()
data = json.dumps(time.mktime(your_date.timetuple())*1000)
return data # data send to javascript
var your_date = new Date(data)
数据来自Python的结果