today parse now create biblioteca javascript python json

javascript - now - python parse date



JSON datetime entre Python y JavaScript (11)

Quiero enviar un objeto datetime.datetime en forma serializada desde Python usando JSON y des-serializar en JavaScript usando JSON. ¿Cuál es la mejor manera de hacer esto?


Al final del juego ... :)

Una solución muy simple es parchear el módulo json por defecto. Por ejemplo:

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

Ahora, puede usar json.dumps () como si siempre hubiera soportado datetime ...

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

Esto tiene sentido si necesita que esta extensión del módulo json siempre se active y no desea cambiar la forma en que usted u otras personas usan la serialización json (ya sea en el código existente o no).

Tenga en cuenta que algunos pueden considerar parchear las bibliotecas de esa manera como una mala práctica. Se debe tener especial cuidado en caso de que desee extender su aplicación en más de una forma. En tal caso, le sugiero que use la solución de ramen o JT y elija la extensión json adecuada en cada caso.


Aparentemente, el formato de fecha JSON (bueno, JavaScript) es el 2012-04-23T18: 25: 43.511Z - UTC y "Z". Sin este JavaScript, utilizará la zona horaria local del navegador web al crear un objeto Date () a partir de la cadena.

Para una hora "ingenua" (lo que Python llama una hora sin zona horaria y se supone que es local), lo siguiente forzará la zona horaria local para que luego pueda convertirse correctamente a 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://.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)

Por qué es tan difícil.


Aquí hay una solución bastante completa para codificar y decodificar recursivamente objetos datetime.datetime y datetime.date usando el módulo json biblioteca estándar. Esto necesita Python> = 2.6 ya que el código de formato %f en la cadena de formato datetime.datetime.strptime () solo es compatible desde entonces. Para el soporte de Python 2.5, elimine el %f y elimine los microsegundos de la cadena de fecha ISO antes de intentar convertirlo, pero perderá la precisión de los microsegundos, por supuesto. Para la interoperabilidad con cadenas de fecha ISO de otras fuentes, que pueden incluir un nombre de zona horaria o un desplazamiento UTC, es posible que también deba eliminar algunas partes de la cadena de fecha antes de la conversión. Para obtener un analizador completo de cadenas de fecha ISO (y muchos otros formatos de fecha), consulte el módulo dateutil terceros.

La decodificación solo funciona cuando las cadenas de fecha ISO son valores en una notación de objeto literal de JavaScript o en estructuras anidadas dentro de un objeto. Las cadenas de fecha ISO, que son elementos de una matriz de nivel superior, no se descodificarán.

Es decir, esto funciona:

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''}

Y esto también:

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

Pero esto no funciona como se esperaba:

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

Aquí está el código:

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


En el lado de 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

En el lado de javascript:

var your_date = new Date(data)

donde los datos son resultado de Python


Lo he resuelto.

Digamos que tienes un objeto datetime de Python, d , creado con datetime.now (). Su valor es:

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

Puede serializarlo a JSON como una cadena datetime ISO 8601:

import json json.dumps(d.isoformat())

El objeto datetime de ejemplo se serializaría como:

''"2011-05-25T13:34:05.787000"''

Este valor, una vez recibido en la capa de Javascript, puede construir un objeto Date:

var d = new Date("2011-05-25T13:34:05.787000");

A partir de Javascript 1.8.5, los objetos Date tienen un método toJSON, que devuelve una cadena en un formato estándar. Para serializar el objeto Javascript anterior a JSON, por lo tanto, el comando sería:

d.toJSON()

Lo que te daría:

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

Esta cadena, una vez recibida en Python, podría deserializarse de nuevo a un objeto de fecha y hora:

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

Esto da como resultado el siguiente objeto de fecha y hora, que es el mismo con el que comenzó y, por lo tanto, correcto:

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



No hay mucho que agregar a la respuesta de la wiki de la comunidad, excepto la marca de tiempo !

Javascript usa el siguiente formato:

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

Lado de Python (para el controlador json.dumps , consulte las otras respuestas):

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

Si deja esa Z fuera, los marcos frontales como angular no pueden mostrar la fecha en la zona horaria local del navegador:

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


Para los proyectos en varios idiomas, descubrí que las cadenas que contienen fechas RfC 3339 son la mejor manera de hacerlo. Una fecha de RfC 3339 se ve así:

1985-04-12T23:20:50.52Z

Creo que la mayor parte del formato es obvio. La única cosa un tanto inusual puede ser la "Z" al final. Es sinónimo de GMT / UTC. También puede agregar un desplazamiento de zona horaria como +02: 00 para CEST (Alemania en verano). Personalmente prefiero mantener todo en UTC hasta que se muestre.

Para la visualización, comparaciones y almacenamiento, puede dejarlo en formato de cadena en todos los idiomas. Si necesita la fecha para los cálculos, puede volver a convertirla en un objeto de fecha nativa en la mayoría de los idiomas.

Así que genera el JSON de esta manera:

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

Desafortunadamente, el constructor de fecha de Javascript no acepta cadenas RfC 3339 pero hay muchos parsers disponibles en Internet.

huTools.hujson trata de manejar los problemas de codificación más comunes con los que puede encontrarse en el código Python, incluidos los objetos de fecha / fecha, mientras se manejan las zonas horarias correctamente.


Puede agregar el parámetro ''predeterminado'' a json.dumps para manejar esto:

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

Que es el formato ISO 8601 .

Una función de manejador por defecto más completa:

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

Actualización: Se agregó salida de tipo así como valor.
Actualización: también manejar fecha


Si está seguro de que solo Javascript consumirá el JSON, prefiero pasar los objetos de Date Javascript directamente.

El método ctime() en objetos de datetime devolverá una cadena que el objeto Fecha de Javascript puede comprender.

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

Javascript con mucho gusto lo usará como un objeto literal, y ya tienes tu objeto Date integrado.


Usando json , puede crear una subclase de JSONEncoder y anular el método predeterminado () para proporcionar sus propios serializadores personalizados:

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)

Entonces, puedes llamarlo así:

>>> DateTimeJSONEncoder().encode([datetime.datetime.now()]) ''["2010-06-15T14:42:28"]''