Fuseau horaire d'analyse datetime incohérent en Python

Nov 23 2020

Quand j'exécute ce qui suit dans Python 3.X

import datetime

DATE_TS_FORMAT = '%Y-%m-%d %H:%M:%S.%f %Z'

date_ts = datetime.datetime(2019, 1, 2, 3, 4, 5, tzinfo=datetime.timezone.utc)
date_ts = date_ts.strftime(DATE_TS_FORMAT)
print(date_ts)
date_ts = datetime.datetime.strptime(date_ts, DATE_TS_FORMAT)
date_ts = date_ts.strftime(DATE_TS_FORMAT)
print(date_ts)

Je reçois

2019-01-02 03:04:05.000000 UTC
2019-01-02 03:04:05.000000 

Pourquoi les informations de fuseau horaire ont-elles disparu et comment puis-je résoudre ce problème?

Réponses

2 MrFuppes Nov 24 2020 at 07:13

Incohérent en effet ... Le fait est que cela %Zfait strptime accepter certaines chaînes (GMT, UTC et toute valeur dans time.tzname - docs ), mais n'en fait rien. Ex:

from datetime import datetime

s = "2019-01-02 03:04:05.000000 UTC"
dt = datetime.strptime(s, '%Y-%m-%d %H:%M:%S.%f %Z')

print(repr(dt))
# datetime.datetime(2019, 1, 2, 3, 4, 5)

L'objet datetime résultant est naïf; plus aucun signe d'UTC.

Pour tenir compte de ce comportement, vous pouvez post-traiter l'objet datetime, quelque chose comme

if "UTC" in s: 
    dt = dt.replace(tzinfo=timezone.utc)

(ce que je pense est un peu douloureux ...) ou remplacez "UTC" par quelque chose qui %zanalyse UTC 1 ,

dt = datetime.strptime(s.replace("UTC", "+00:00"), '%Y-%m-%d %H:%M:%S.%f %z')

print(repr(dt))
# datetime.datetime(2019, 1, 2, 3, 4, 5, tzinfo=datetime.timezone.utc)

(ce que je trouve un peu moche ...) ou utilisez un analyseur approprié, par exemple

from dateutil.parser import parse

dt = parse(s)

print(repr(dt))
# datetime.datetime(2019, 1, 2, 3, 4, 5, tzinfo=tzutc())

print(dt.strftime('%Y-%m-%d %H:%M:%S.%f %Z'))
# 2019-01-02 03:04:05.000000 UTC

(ce qui sera un peu plus lent si les performances sont un problème ...).


1 OMI, cela est également incohérent; "+00: 00" peut également être le décalage UTC d'un fuseau horaire qui a un décalage UTC de 0 heure à ce moment-là ...