Comment convertir un objet time.struct_time en un objet datetime?

288

Comment convertir un time.struct_timeobjet Python en datetime.datetimeobjet?

J'ai une bibliothèque qui fournit la première et une deuxième bibliothèque qui veut la seconde.

static_rtti
la source

Réponses:

384

Utilisez time.mktime () pour convertir le tuple temporel (en heure locale) en secondes depuis l'époque, puis utilisez datetime.fromtimestamp () pour obtenir l'objet datetime.

from datetime import datetime
from time import mktime

dt = datetime.fromtimestamp(mktime(struct))
Rod Hyde
la source
45
Notez que cela échoue avant 1900. Les gens modernes ne se souviennent jamais de cette limitation!
mlissner
3
cela va-t-il perdre les tm_isdstdonnées? Je pense que oui, le résultat datetime objet reste naïf dans la mesure de revenir Nonesur .dst()même si struct.tm_isdstest 1.
n611x007
3
Cela fonctionnera généralement. Cependant, il échouera si le tuple temporel dépasse les valeurs acceptées par mktime, par exemple pour la valeur (1970, 1, 1, 0, 0, 0, 0, 1, -1). J'ai rencontré cela après avoir analysé l'en-tête Date sur une demande HTTP qui a renvoyé ce tuple.
user3820547
3
@richvdh: la norme C spécifie que cela mktime()devrait prendre tm_isdsten compte et Python time.mktime()appelle la mktime()fonction C sur CPython. mktime()peut choisir la mauvaise heure locale lorsqu'elle est ambiguë (par exemple, pendant la transition de fin de DST ("repli")) si struct.tm_isdstest -1ou si mktime()sur la plate-forme donnée ignore l' entrée tm_isdst . De plus, si le fuseau horaire local avait un décalage utc différent dans le passé et que C mktime()n'utilise pas une base de données tz historique qui peut fournir les anciennes valeurs de décalage utc, il mktime()peut également renvoyer une valeur incorrecte (par exemple, d'une heure).
jfs
1
@naxa: si mktime()n'ignore pas tm_isdstsur la plate-forme donnée (il le fait sur la mienne), alors fromtimestamp()perd définitivement l'info: l' objet naïf renvoyé datetimereprésentant l'heure locale peut être ambigu (horodatage -> l'heure locale est déterministe (si nous ignorons les secondes intercalaires) mais local time -> timestamp may be ambiguous e.g., during end-of-DST transition). Also, fromtimestamp () `peut choisir un décalage utc incorrect s'il n'utilise pas une base de données tz historique.
jfs
123

Comme ça:

>>> structTime = time.localtime()
>>> datetime.datetime(*structTime[:6])
datetime.datetime(2009, 11, 8, 20, 32, 35)
Nadia Alramli
la source
3
N'oubliez pas de #import time, datetime
jhwist
7
@jhwist - certaines choses que les gens peuvent faire confiance pour le découvrir par eux-mêmes :)
orip
14
@rodling la syntaxe *et **vous permet de développer un objet de type listy ou dicty dans des arguments séparés - c'est l'un de mes morceaux préférés de Python. Voir docs.python.org/2/tutorial/… pour plus d'informations
OrganicPanda
10
N'oubliez pas que cela vous donnera une ValueError si le struct_time a une seconde, par exemple:t=time.strptime("30 Jun 1997 22:59:60", "%d %b %Y %H:%M:%S"); datetime.datetime(*t[:6])
berdario
7
@berdario: pour retourner des valeurs compatibles avec datetime: datetime(*t[:5]+(min(t[5], 59),))par exemple, pour accepter "2015-06-30 16:59:60 PDT".
jfs
37

Ce n'est pas une réponse directe à votre question (qui a déjà été assez bien répondu). Cependant, ayant eu plusieurs fois des morsures sur le fondement, je ne saurais trop insister sur le fait qu'il vous incomberait de regarder de près ce que votre objet time.struct_time fournit, par rapport à ce que d'autres champs de temps peuvent avoir.

En supposant que vous avez à la fois un objet time.struct_time et une autre chaîne de date / heure, comparez les deux et assurez-vous de ne pas perdre de données et de créer par inadvertance un objet datetime naïf, lorsque vous pouvez faire autrement.

Par exemple, l'excellent module feedparser renverra un champ "publié" et peut renvoyer un objet time.struct_time dans son champ "published_parsed":

time.struct_time(tm_year=2013, tm_mon=9, tm_mday=9, tm_hour=23, tm_min=57, tm_sec=42, tm_wday=0, tm_yday=252, tm_isdst=0)

Notez maintenant ce que vous obtenez réellement avec le champ "publié".

Mon, 09 Sep 2013 19:57:42 -0400

Par Stallman 's Beard! Informations sur le fuseau horaire!

Dans ce cas, l'homme paresseux pourrait vouloir utiliser l'excellent module dateutil pour conserver les informations de fuseau horaire:

from dateutil import parser
dt = parser.parse(entry["published"])
print "published", entry["published"])
print "dt", dt
print "utcoffset", dt.utcoffset()
print "tzinfo", dt.tzinfo
print "dst", dt.dst()

ce qui nous donne:

published Mon, 09 Sep 2013 19:57:42 -0400
dt 2013-09-09 19:57:42-04:00
utcoffset -1 day, 20:00:00
tzinfo tzoffset(None, -14400)
dst 0:00:00

On pourrait alors utiliser l'objet datetime sensible au fuseau horaire pour normaliser tout le temps en UTC ou tout ce que vous pensez être génial.

lysdexia
la source
7
Tous les *_parsedchamps de feedparsed sont déjà normalisés en UTC comme cela peut être vérifié dans la documentation d'analyse de date, donc c'est redondant.
itorres
1
@itorres: Si je comprends bien, cette réponse ne concerne pas la normalisation en UTC, mais la conservation des informations de fuseau horaire dans un datetimeobjet qui est perdu lors de l' feedparseranalyse des dates de chaîne brutes.
davidag