2010-08-10 29 views
25

Quiero convertir un horario de Python a un RFC 2822 datetime. He intentado estos métodos en vano:Convertir Python datetime a rfc 2822

>>> from email.Utils import formatdate 
>>> import datetime 
>>> formatdate(datetime.datetime.now()) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/email /utils.py", line 159, in formatdate 
    now = time.gmtime(timeval) 
TypeError: a float is required 

Respuesta

36

Aquí hay un código de trabajo, desglosado en piezas sencillas simplemente para mayor claridad:

>>> import datetime 
>>> import time 
>>> from email import utils 
>>> nowdt = datetime.datetime.now() 
>>> nowtuple = nowdt.timetuple() 
>>> nowtimestamp = time.mktime(nowtuple) 
>>> utils.formatdate(nowtimestamp) 
'Tue, 10 Aug 2010 20:43:53 -0000' 

Explicación: email.utils.formatdate quiere una marca de tiempo - es decir, una flotar con segundos (y fracción del mismo) desde la época. Una instancia datetime no le da una marca de tiempo directamente, pero puede darle una tupla de tiempo con el método timetuple, y time.mktime por supuesto puede hacer una marca de tiempo de dicha tupla.

+1

¿por qué no simplemente usar time.time()? –

+2

En la versión 3.3 'datetime' tiene el método' timestamp', por lo que este proceso es mucho más rápido. –

23

Si realmente desea la hora actual, acaba de llamar formatdate sin argumentos:

>>> from email.Utils import formatdate 
>>> formatdate() 
'Tue, 10 Aug 2010 20:40:23 -0000' 

Pero, si debe pasar un argumento, desea que la salida de time.time (un número de segundos desde el 01/01/1970):

>>> import time 
>>> formatdate(time.time()) 
'Tue, 10 Aug 2010 20:41:43 -0000' 

Fwiw, datetime.datetime.now() devuelve un objeto datetime, que no es lo que formatdate espera.

Editado para agregar: si ya tiene un objeto de fecha y hora, puede dar formato de manera apropiada para formatDate:

>>> import datetime 
>>> dt = datetime.datetime.now() 
>>> formatdate(float(dt.strftime('%s'))) 
'Tue, 10 Aug 2010 20:46:16 -0000' 

Editado: Alex Martelli señaló que la cadena de formato '% s' para strftime puede no ser portátil a través de plataformas. Una posible alternativa sería, como él mismo sugirió,

>>> formatdate(time.mktime(dt.timetuple())) 
'Tue, 10 Aug 2010 20:46:16 -0000' 
+0

interesante - el 'formato s'' '% a' aparece strftime' ser indocumentado, y por lo tanto uno de los que "funcionan en algunas plataformas" (pero no en todos), a menos que tengas documentos que lo muestren, funcionará multiplataforma. –

+0

En realidad, esa es la cadena de formato que toma el comando "fecha" de Unix para dar salida al tiempo basado en época, lo usé sin pensarlo y funcionó :) Lo verificaré y te responderé (o cambiaré mi respuesta). – rbp

+0

Bueno, http://docs.python.org/library/datetime.html#strftime-strptime-behavior establece que "El conjunto completo de códigos de formato admitidos varía en todas las plataformas, porque Python llama a la función strftime() de la biblioteca de la plataforma C, y las variaciones de la plataforma son comunes ". Y, en Linux, man 3 strftime lista '% s' como un posible valor de formato. Entonces, supongo que tienes razón, es probable que no sea portátil. Gracias :) – rbp

5

Python 3.3, además de los métodos mencionados por otros comentaristas, se añade también un método format_datetime, que es mucho más limpio:

>>> import datetime 
>>> import email.utils 
>>> dt = datetime.datetime.now() 
>>> email.utils.format_datetime(dt) 
'Thu, 09 Mar 2017 10:50:00 -0000'