我想发送一个datetime。从Python中使用JSON序列化datetime对象,并在JavaScript中使用JSON反序列化。最好的方法是什么?
如果你确定只有Javascript会使用JSON,我更喜欢直接传递Javascript Date对象。
datetime对象上的ctime()方法将返回一个Javascript Date对象可以理解的字符串。
import datetime
date = datetime.datetime.today()
json = '{"mydate":new Date("%s")}' % date.ctime()
Javascript会很乐意使用它作为对象文字,这样就有了内置的Date对象。
对于跨语言项目,我发现包含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对象。
你可以将'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,你可以子类化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"]'
Here's a fairly complete solution for recursively encoding and decoding datetime.datetime and datetime.date objects using the standard library json module. This needs Python >= 2.6 since the %f format code in the datetime.datetime.strptime() format string is only supported in since then. For Python 2.5 support, drop the %f and strip the microseconds from the ISO date string before trying to convert it, but you'll loose microseconds precision, of course. For interoperability with ISO date strings from other sources, which may include a time zone name or UTC offset, you may also need to strip some parts of the date string before the conversion. For a complete parser for ISO date strings (and many other date formats) see the third-party dateutil module.
只有当ISO日期字符串是JavaScript中的值时,解码才有效 文字对象表示法或在对象内的嵌套结构中。ISO日期 作为顶级数组项的字符串将不会被解码。
例如:
date = 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))
我已经算出来了。
假设你有一个Python datetime对象d,是用datetime.now()创建的。其值为:
datetime.datetime(2011, 5, 25, 13, 34, 5, 787000)
你可以将它序列化为JSON格式的ISO 8601 datetime字符串:
import json
json.dumps(d.isoformat())
示例datetime对象将被序列化为:
'"2011-05-25T13:34:05.787000"'
这个值一旦在Javascript层接收到,就可以构造一个Date对象:
var d = new Date("2011-05-25T13:34:05.787000");
从Javascript 1.8.5开始,Date对象有一个toJSON方法,它以标准格式返回一个字符串。因此,要将上述Javascript对象序列化回JSON,命令将是:
d.toJSON()
这将给你:
'2011-05-25T20:34:05.787Z'
这个字符串一旦在Python中接收到,就可以反序列化回datetime对象:
datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ')
这将导致以下datetime对象,它与您开始时的对象相同,因此是正确的:
datetime.datetime(2011, 5, 25, 20, 34, 5, 787000)
在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的结果
游戏后期……:)
一个非常简单的解决方案是给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扩展。
除了时间戳之外,没有什么要添加到社区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"
显然,“正确”的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)
为什么这么难呢?
对于Python到JavaScript的日期转换,日期对象需要是特定的ISO格式,即ISO格式或UNIX编号。如果ISO格式缺少一些信息,那么您可以使用Date将其转换为Unix编号。首先解析。此外,日期。parse也适用于React,而new Date可能会触发异常。
如果您有一个没有毫秒的DateTime对象,则需要考虑以下内容。:
var unixDate = Date.parse('2016-01-08T19:00:00')
var desiredDate = new Date(unixDate).toLocaleDateString();
示例日期同样可以是结果中的变量。API调用后的数据对象。
有关以所需格式显示日期的选项(例如,显示较长的工作日),请查看MDN文档。
简单地这样做:
r = json.dumps(your_json_data, default=str)
your_json_data = json.loads(r)
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用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对齐