我想发送一个datetime。从Python中使用JSON序列化datetime对象,并在JavaScript中使用JSON反序列化。最好的方法是什么?


当前回答

除了时间戳之外,没有什么要添加到社区wiki答案中!

Javascript使用以下格式:

new Date().toJSON() // "2016-01-08T19:00:00.123Z"

Python端(用于json。转储处理程序,见其他答案):

>>> 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"

其他回答

简单地这样做:

r = json.dumps(your_json_data, default=str)
your_json_data = json.loads(r)

在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

javascript方面:

var your_date = new Date(data)

哪里的数据是python的结果

除了时间戳之外,没有什么要添加到社区wiki答案中!

Javascript使用以下格式:

new Date().toJSON() // "2016-01-08T19:00:00.123Z"

Python端(用于json。转储处理程序,见其他答案):

>>> 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"

对于跨语言项目,我发现包含RfC 3339日期的字符串是最好的方法。RfC 3339日期如下所示:

  1985-04-12T23:20:50.52Z

我认为大部分格式都是显而易见的。唯一有点不同寻常的可能是结尾的“Z”。它代表GMT/UTC。您还可以添加时区偏移,例如CEST(德国夏季)的+02:00。我个人更喜欢将所有内容都保持UTC格式,直到显示出来。

为了显示、比较和存储,您可以在所有语言中使用字符串格式。如果你需要日期进行计算,很容易将其转换回大多数语言的原生日期对象。

这样生成JSON:

  json.dump(datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ'))

不幸的是,Javascript的Date构造函数不接受RfC 3339字符串,但在互联网上有很多可用的解析器。

huTools。hujson试图处理你在Python代码中可能遇到的最常见的编码问题,包括正确处理时区的date/datetime对象。

游戏后期……:)

一个非常简单的解决方案是给json模块的默认设置打补丁。 例如:

import json
import datetime

json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)

现在,您可以使用json.dumps(),就好像它一直支持datetime…

json.dumps({'created':datetime.datetime.now()})

如果你需要对json模块进行扩展,并且不希望改变你或其他人使用json序列化的方式(无论是在现有代码中还是不在现有代码中),这是有意义的。

注意,有些人可能认为以这种方式修补库是一种糟糕的做法。 如果您希望以多种方式扩展应用程序,则需要特别注意-在这种情况下,我建议使用ramen或JT的解决方案,并在每种情况下选择适当的json扩展。