2010-08-10 15 views
25

Desidero convertire un datetime Python in un datetime RFC 2822. Ho provato questi metodi senza alcun risultato:Convertire Python datetime in 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 

risposta

36

Ecco alcuni codice di lavoro, suddivisi in pezzi semplici solo per chiarezza:

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

Spiegazione: email.utils.formatdate vuole un timestamp - vale a dire, un fluttuare con i secondi (e le sue frazioni) dall'epoca. Un'istanza datetime non fornisce direttamente una data/ora, ma è possibile fornire una tupla di tempo con il metodo timetuple, e time.mktime ovviamente può quindi effettuare un timestamp da tale tupla.

+1

perché non usare solo time.time()? –

+2

Nella versione 3.3 'datetime' ha il metodo' timestamp', rendendo questo processo molto più veloce. –

23

Se si vuole davvero l'ora corrente, basta chiamare formatdate senza argomenti:

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

Ma, se si deve passare un argomento, è vogliono l'uscita di time.time (un certo numero di secondi dal 01/01/1970):

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

FWIW, datetime.datetime.now() restituisce un oggetto datetime, che non è quello che si aspetta formatdate.

A cura di aggiungere: se si dispone già di un oggetto datetime, è possibile formattare in modo appropriato per FormatoData:

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

Modificato: Alex Martelli ha osservato che stringa di formato il '% s' per strftime potrebbe non essere portatile attraverso piattaforme. Una possibile alternativa sarebbe, come egli stesso ha suggerito,

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

Interessante - il 'format s'' '% a' appare strftime' essere non documentato, e quindi uno di quelli che "funzionano su alcune piattaforme" (ma non su tutti) - a meno che non si disponga di documenti che lo dimostrino _will_ work cross-platform? –

+0

In realtà, questa è la stringa di formato che il comando Unix "date" impiega per generare un tempo basato sull'epoca, l'ho usato senza pensare e ha funzionato :) Controllerò e ricontatterei (o cambiare la mia risposta). – rbp

+0

Bene, http://docs.python.org/library/datetime.html#strftime-strptime-behavior afferma che "L'intero set di codici di formato supportati varia tra piattaforme, perché Python chiama la funzione strftime() della libreria C della piattaforma, e le variazioni della piattaforma sono comuni. " E, su Linux, man 3 liste di strftime '% s' come valore di formato possibile. Quindi suppongo che tu abbia ragione, è probabile che non sia portatile. Grazie :) – rbp

5

Python 3.3, in aggiunta ai metodi citati da altri commentatori, anche aggiunto un metodo format_datetime, che è molto più pulito:

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