2010-08-10 8 views
25

Ich möchte eine Python-Datetime in eine RFC 2822 Datetime konvertieren. Ich habe diese Methoden ohne Erfolg versucht:Convert 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 

Antwort

36

Hier einige Arbeitscode, aufgeschlüsselt in einfache Stücke nur für Klarheit:

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

Erläuterung: email.utils.formatdate will einen Zeitstempel - das heißt ein float mit Sekunden (und Bruchteil davon) seit der Epoche. Eine datetime Instanz gibt Ihnen keinen Zeitstempel direkt - aber, es kann geben Sie eine Zeit-Tupel mit der timetuple Methode, und time.mktime kann natürlich dann einen Zeitstempel aus einem solchen Tupel machen.

+1

warum nicht einfach time.time() verwenden? –

+2

In der Version 3.3 hat 'datetime' die' timestamp' Methode, wodurch dieser Prozess viel schneller wird. –

23

Wenn Sie in der Tat die aktuelle Zeit wollen, rufen Sie einfach formatdate ohne Argumente:

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

Aber, wenn Sie es ein Argument übergeben müssen Sie soll die Ausgabe von time.time (Anzahl der Sekunden seit dem 01.01.1970):

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

FWIW, datetime.datetime.now() ein datetime Objekt zurückgibt, die ist nicht was formatdate erwartet.

Edited hinzufügen: Wenn Sie bereits ein Datetime-Objekt haben, können Sie es passend für Formatformatieren können:

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

Editiert: Alex Martelli stellte fest, dass die Zeichenfolge ‚% s‘ Format für strftime nicht tragbar sein kann über Plattformen. Eine mögliche Alternative wäre, wie er selbst vorgeschlagen,

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

Interessant - die ' '% s'' Format' strftime' erscheint Undokumentiert zu sein, und somit einer von denen, die "zufällig auf einigen Plattformen funktionieren" (aber nicht auf allen) - es sei denn, Sie haben Dokumente, die es zeigen _wird plattformübergreifend arbeiten? –

+0

Eigentlich ist das die Formatzeichenfolge, die der Unix-Befehl "date" benötigt, um epochale Zeit auszugeben, ich habe sie ohne nachzudenken verwendet und es hat funktioniert :) Ich überprüfe und melde mich bei dir (oder ändere meine Antwort). – rbp

+0

Nun, http://docs.python.org/library/datetime.html#strftime-strptime-behavior gibt an, dass "die vollständige Liste der unterstützten Formatcodes von Plattform zu Plattform variiert, weil Python die strftime() - Funktion der Plattform C-Bibliothek aufruft. und Plattformvariationen sind üblich. " Unter Linux listet Mann 3 strftime '% s' als möglichen Formatwert auf. Ich nehme an, Sie haben Recht, es ist wahrscheinlich nicht tragbar. Danke :) – rbp

5

Python 3.3, zusätzlich zu den von anderen commen genannten Verfahren, fügte auch eine format_datetime Methode, die viel sauberer ist:

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