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


当前回答

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

其他回答

简单地这样做:

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

对于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文档。

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

显然,“正确”的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)

为什么这么难呢?

如果你确定只有Javascript会使用JSON,我更喜欢直接传递Javascript Date对象。

datetime对象上的ctime()方法将返回一个Javascript Date对象可以理解的字符串。

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

Javascript会很乐意使用它作为对象文字,这样就有了内置的Date对象。