Le fuseau horaire est un problème difficile. L’heure d’été est encore plus difficile. Je me suis retrouvé à rencontrer des problèmes et des problèmes lorsque j’ai commencé à utiliser correctement datetime en Python. Je décide donc d’écrire un blog pour partager mon expérience.

« Naïf » et « Conscient »

La première chose à savoir est qu’en Python, il existe deux types de datetime: offset-naive et offset-aware. Le décalage naïf signifie que datetime n’a pas d’informations sur le fuseau horaire. Cela pourrait être très sujet aux erreurs si vous êtes nouveau sur Python. Si vous mélangez un datetime naïf et un datetime conscient, vous obtiendrez une erreur. Et Python n’a pas de support de fuseau horaire intégré, vous devez utiliser pytz, un module pour les informations sur le fuseau horaire.

import pytz
from datetime import datetimetznaive_datetime = datetime(2018, 1, 1, 12, 0)
tzaware_datetime = datetime(2018, 1, 1, 12, 0, tzinfo=pytz.utc)# this will raise an error
tznaive_datetime == tzaware_datetime

Pour éviter ce genre de problème, vous devrez vous assurer que vos objets datetime sont toujours naïfs de décalage ou toujours conscients du décalage. Mais nous ne pouvons pas éviter de traiter avec le fuseau horaire, donc ma meilleure pratique est de toujours travailler avec datetime conscient du décalage.

La valeur par défaut de Python est datetime naïve. now() renvoie une date-heure naïve dans votre fuseau horaire local, et utcnow() renvoie également une date-heure naïve, même la fonction indique déjà le fuseau horaire UTC ! Vous aurez besoin du module pytz et également du module tzlocal pour bien faire les choses. Voici comment j’obtiens du temps avec le bon fuseau horaire.

import datetime
import pytz
import tzlocaldef utcnow():
return pytz.utc.localize(datetime.utcnow())def now():
return tzlocal.get_localzone().localize(datetime.now())

Analyse de la date et de l’heure avec le fuseau horaire

Mise à jour: C’est seulement un problème en Python 2

Une autre surprise est que l’analyseur python strptime ne fonctionne pas avec le fuseau horaire. Le code ci-dessous échouera.

>>> from datetime import datetime
>>> datetime.strptime('2017-11-15T12:00:00-0700', '%Y-%m-%dT%H:%M:%S%z')ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%m:%S%z'

Pour analyser datetime avec timezone, vous aurez besoin d’un autre module python-dateutil. Ce module fournit un analyseur qui fonctionnera avec le fuseau horaire. Maintenant, vous pouvez analyser datetime avec le fuseau horaire!

>>> from dateutil import parser
>>> parser.parse('2017-11-15T12:00:00-07')datetime.datetime(2017, 11, 15, 12, 0, tzinfo=tzoffset(None, -25200))

Timedelta et DST

La dernière chose que vous devez faire attention lors de la manipulation de datetime sensible au décalage. pytz vous aidera à savoir si une date est sous influence de l’heure d’été en vérifiant la méthode dst().

>>> import pytz
>>> pst = pytz.timezone("US/Pacific")
>>> pst.localize(datetime(2017, 10, 1)).dst()
datetime.timedelta(0, 3600)
>>> pst.localize(datetime(2017, 12, 1)).dst()
datetime.timedelta(0)

Remarque: L’heure d’été de 2017 s’est terminée le 5 novembre. Ainsi, toute date après le 5 novembre aura timedelta(0)

Mais les informations dst() ne sont pas mises à jour lorsque vous manipulez le datetime

>>> (pst.localize(datetime(2017, 10, 1)) + timedelta(days=60)).dst()
datetime.timedelta(0, 3600)

Ce que vous pouvez vraiment faire est de convertir en datetime à décalage naïf, puis d’appliquer le delta…

pst.localize(yourdate.replace(tzinfo=None) + td).dst()

Résumé

Travailler avec Datetime en Python est sujet aux erreurs. C’est parce que Python ne prend pas bien en charge la date et le fuseau horaire. Vous devrez utiliser beaucoup de modules supplémentaires. Cependant, il y a en fait une solution miracle, vous pouvez simplement utiliser arrow. Ce module remplace le module datetime python, et il est toujours compatible avec les décalages, et il résout également tous les problèmes que je mentionne ci-dessus. La seule chose qui peut m’inquiéter est l’intégration avec d’autres applications externes comme Spark.