Python strptime () et timezones?

j'ai un fichier dump CSV d'un BlackBerry IPD backup, créé en utilisant IPDDump. Les chaînes date / heure ici ressemblent à quelque chose comme ceci (où EST est un fuseau horaire Australien):

Tue Jun 22 07:46:22 EST 2010

j'ai besoin de pouvoir analyser cette date en Python. Au début, j'ai essayé d'utiliser la fonction strptime() de datettime.

>>> datetime.datetime.strptime('Tue Jun 22 12:10:20 2010 EST', '%a %b %d %H:%M:%S %Y %Z')

Cependant, pour une raison quelconque, l'objet datetime qui revient ne semble pas avoir de tzinfo associés.

j'ai lu sur cette page qu'apparemment datetime.strptime se débarrasse silencieusement tzinfo , cependant, j'ai vérifié la documentation, et je ne peux rien trouver à cet effet documenté ici .

j'ai pu obtenir la date analysée en utilisant une bibliothèque Python tiers, dateutil , cependant je suis toujours curieux de savoir comment j'ai utilisé la strptime() mal construit? Y a-t-il un moyen d'obtenir strptime() pour jouer gentiment avec timezones?

117
demandé sur victorhooi 2010-07-22 06:42:08

3 réponses

Le datetime documentation du module dit:

renvoie une date-heure correspondant à date_string, divisée selon le format. Cela équivaut à datetime(*(time.strptime(date_string, format)[0:6])) .

vous voyez ce [0:6] ? Ça te donne (year, month, day, hour, minute, second) . Rien d'autre. Aucune mention de timezones.

fait intéressant, [Win XP SP2, Python 2.6, 2.7] passer votre exemple à time.strptime ne fonctionne pas mais si vous enlevez le "%Z" et le "EST" ÇA MARCHE. Aussi en utilisant "UTC" ou" GMT "au lieu de" EST " fonctionne. "PST" et" MEZ " ne marchent pas. Déroutant.

il est intéressant de noter que ceci a été mis à jour à partir de la version 3.2 et la même documentation indique maintenant aussi ce qui suit:

lorsque la directive %z est fournie à la méthode strptime (), un objet aware datetime sera produit. Le tzinfo du résultat sera défini à une instance timezone.

notez que cela ne fonctionne pas avec %Z, donc le cas est important. Voir l'exemple suivant:

In [1]: from datetime import datetime

In [2]: start_time = datetime.strptime('2018-04-18-17-04-30-AEST','%Y-%m-%d-%H-%M-%S-%Z')

In [3]: print("TZ NAME: {tz}".format(tz=start_time.tzname()))
TZ NAME: None

In [4]: start_time = datetime.strptime('2018-04-18-17-04-30-+1000','%Y-%m-%d-%H-%M-%S-%z')

In [5]: print("TZ NAME: {tz}".format(tz=start_time.tzname()))
TZ NAME: UTC+10:00
32
répondu John Machin 2018-04-18 08:35:57

je recommande d'utiliser python-dateutil . Son analyseur a pu analyser chaque format de date que je lui ai lancé jusqu'à présent.

>>> from dateutil import parser
>>> parser.parse("Tue Jun 22 07:46:22 EST 2010")
datetime.datetime(2010, 6, 22, 7, 46, 22, tzinfo=tzlocal())
>>> parser.parse("Fri, 11 Nov 2011 03:18:09 -0400")
datetime.datetime(2011, 11, 11, 3, 18, 9, tzinfo=tzoffset(None, -14400))
>>> parser.parse("Sun")
datetime.datetime(2011, 12, 18, 0, 0)
>>> parser.parse("10-11-08")
datetime.datetime(2008, 10, 11, 0, 0)

et ainsi de suite. Ne pas traiter avec strptime() non-sens de format... il suffit de jeter un jour et il Fait La bonne Chose.

Mise À Jour : Oups. J'ai manqué à votre question initiale que vous avez mentionné que vous avez utilisé dateutil , désolé. Mais j'espère que ce la réponse est toujours utile pour d'autres personnes qui trébuchent sur cette question quand ils ont date questions parsing et voir l'utilité de ce module.

297
répondu Joe Shaw 2011-12-15 18:52:19

votre chaîne de temps est similaire au format de temps dans rfc 2822 (date format in email, en-têtes http) . Vous pouvez le parcourir en utilisant seulement stdlib:

>>> from email.utils import parsedate_tz
>>> parsedate_tz('Tue Jun 22 07:46:22 EST 2010')
(2010, 6, 22, 7, 46, 22, 0, 1, -1, -18000)

voir solutions qui produisent des objets datetime sensibles au fuseau horaire pour différentes versions de Python: parsing date with timezone from an email .

dans ce format, EST est sémantiquement équivalent à -0500 . Bien que, en général, une abréviation de fuseau horaire n'est pas suffisante, pour identifier un fuseau horaire uniquement .

9
répondu jfs 2017-05-23 12:26:32