Python和JavaScript之间的JSONdate时间

我想用Python使用JSON以序列化的forms发送一个datetime.datetime对象,并使用JSON在JavaScript中进行反序列化。 什么是最好的方法来做到这一点?

你可以添加'default'参数给json.dumps来处理:

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

更新:添加types的输出以及值。
更新:也处理date

对于跨语言项目,我发现包含RfC 3339date的string是最好的方法。 RfC 3339date如下所示:

  1985-04-12T23:20:50.52Z 

我认为大部分格式是显而易见的。 唯一有点不寻常的可能是最后的“Z”。 它代表GMT / UTC。 您也可以为CEST(德国夏季)添加+02:00的时区偏移量。 我个人比较喜欢用UTC保存所有内容,直到显示出来。

为了显示,比较和存储,您可以将其保留为所有语言的string格式。 如果你需要计算date,很容易把它转换回大多数语言的本地date对象。

因此,生成这样的JSON:

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

不幸的是Javascriptdate构造函数不接受RfC 3339string,但在Internet上有许多parsing器可用。

huTools.hujson尝试处理在Python代码中遇到的最常见的编码问题,包括date/date时间对象,同时正确处理时区。

我已经完成了。

假设您有一个Pythondate时间对象d ,使用datetime.now()创build。 它的价值是:

 datetime.datetime(2011, 5, 25, 13, 34, 5, 787000) 

您可以将其作为ISO 8601date时间string序列化为JSON:

 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方法,它返回一个标准格式的string。 为了将上面的JavaScript对象序列化回JSON,因此,命令是:

 d.toJSON() 

哪个会给你:

 '2011-05-25T20:34:05.787Z' 

这个string,一旦被Python接收,就可以被反序列化回date时间对象:

 datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ') 

这导致下面的date时间对象,这是你开始使用,因此是正确的:

 datetime.datetime(2011, 5, 25, 20, 34, 5, 787000) 

使用json ,你可以inheritanceJSONEncoder并覆盖默认的()方法来提供你自己的自定义序列化器:

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

这里有一个相当完整的解决scheme,使用标准库json模块对datetime.datetime和datetime.date对象进行recursion编码和解码。 这需要Python> = 2.6,因为datetime.datetime.strptime()格式string中的%f格式代码只在那时被支持。 对于Python 2.5的支持,在尝试转换之前,放弃%f并从ISOdatestring中去除微秒,但是当然,你将失去微秒精度。 为了与其他来源(包括时区名称或UTC偏移量)的ISOdatestring进行互操作,您可能还需要在转换之前去除datestring的某些部分。 有关ISOdatestring(以及许多其他date格式)的完整parsing器,请参阅第三方dateutil模块。

仅当ISOdatestring是JavaScript文字对象表示法中的值或对象内的嵌套结构时,解码才起作用。 作为顶级数组的项目的ISOdatestring将不会被解码。

即这个作品:

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

如果您确定只有JavaScript将使用JSON,则我更愿意直接传递Javascript Date对象。

datetime对象上的ctime()方法将返回Javascriptdate对象可以理解的string。

 import datetime date = datetime.datetime.today() json = '{"mydate":new Date("%s")}' % date.ctime() 

Javascript会很高兴地使用它作为一个对象字面值,并且你已经有了你的Date对象。

在游戏后期… 🙂

一个非常简单的解决scheme是修补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序列化(无论是在现有的代码或不)。

请注意,有些人可能会认为以这种方式修补库是不好的做法。 如果您希望以多种方式扩展您的应用程序,则需要特别注意 – 这种情况下,我build议使用拉面或JT的解决scheme,并在每种情况下select适当的json扩展。

没有太多添加到社区维基答案,除了时间戳

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这样的前端框架不能在浏览器本地时区中显示date:

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

在JavaScript方面:

 var your_date = new Date(data) 

数据是python的结果

我的build议是使用图书馆。 在pypi.org有几个可用的。

我用这个,效果很好: https : //pypi.python.org/pypi/asjson