我想发送一个datetime。从Python中使用JSON序列化datetime对象,并在JavaScript中使用JSON反序列化。最好的方法是什么?
当前回答
显然,“正确”的JSON (JavaScript)日期格式是2012-04-23T18:25:43.511Z - UTC和“Z”。如果不这样做,JavaScript在从字符串创建Date()对象时将使用web浏览器的本地时区。
对于“天真”时间(Python称之为没有时区的时间,这里假设是本地时间),下面将强制使用本地时区,以便它可以正确地转换为UTC:
def default(obj):
if hasattr(obj, "json") and callable(getattr(obj, "json")):
return obj.json()
if hasattr(obj, "isoformat") and callable(getattr(obj, "isoformat")):
# date/time objects
if not obj.utcoffset():
# add local timezone to "naive" local time
# https://stackoverflow.com/questions/2720319/python-figure-out-local-timezone
tzinfo = datetime.now(timezone.utc).astimezone().tzinfo
obj = obj.replace(tzinfo=tzinfo)
# convert to UTC
obj = obj.astimezone(timezone.utc)
# strip the UTC offset
obj = obj.replace(tzinfo=None)
return obj.isoformat() + "Z"
elif hasattr(obj, "__str__") and callable(getattr(obj, "__str__")):
return str(obj)
else:
print("obj:", obj)
raise TypeError(obj)
def dump(j, io):
json.dump(j, io, indent=2, default=default)
为什么这么难呢?
其他回答
你可以将'default'参数添加到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))
更新:增加了类型和值的输出。 更新:也处理日期
显然,“正确”的JSON (JavaScript)日期格式是2012-04-23T18:25:43.511Z - UTC和“Z”。如果不这样做,JavaScript在从字符串创建Date()对象时将使用web浏览器的本地时区。
对于“天真”时间(Python称之为没有时区的时间,这里假设是本地时间),下面将强制使用本地时区,以便它可以正确地转换为UTC:
def default(obj):
if hasattr(obj, "json") and callable(getattr(obj, "json")):
return obj.json()
if hasattr(obj, "isoformat") and callable(getattr(obj, "isoformat")):
# date/time objects
if not obj.utcoffset():
# add local timezone to "naive" local time
# https://stackoverflow.com/questions/2720319/python-figure-out-local-timezone
tzinfo = datetime.now(timezone.utc).astimezone().tzinfo
obj = obj.replace(tzinfo=tzinfo)
# convert to UTC
obj = obj.astimezone(timezone.utc)
# strip the UTC offset
obj = obj.replace(tzinfo=None)
return obj.isoformat() + "Z"
elif hasattr(obj, "__str__") and callable(getattr(obj, "__str__")):
return str(obj)
else:
print("obj:", obj)
raise TypeError(obj)
def dump(j, io):
json.dump(j, io, indent=2, default=default)
为什么这么难呢?
游戏后期……:)
一个非常简单的解决方案是给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扩展。
简单地这样做:
r = json.dumps(your_json_data, default=str)
your_json_data = json.loads(r)
除了时间戳之外,没有什么要添加到社区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"
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- Babel 6改变了它导出默认值的方式
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何配置历史记录?
- ES6模板文字可以在运行时被替换(或重用)吗?
- [Vue警告]:找不到元素
- 查询JSON类型内的数组元素
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 可以在setInterval()内部调用clearInterval()吗?
- AngularJS控制器的生命周期是什么?
- 无法读取未定义的属性“msie”- jQuery工具
- 将旋转的xtick标签与各自的xtick对齐