Tidsomstilling er et hårdt problem. DST er endnu et sværere problem. Jeg befandt mig i at gå ind i problemer og problemer, da jeg begyndte at bruge datetime i Python korrekt. Så jeg beslutter at skrive en blog for at dele min oplevelse.

“naiv” og “bevidst”

den første ting at vide er, at der i Python er to typer datetime: offset-naiv og offset-bevidst. Offset naiv betyder, at datetime ikke har nogen tidsinformation. Det kan være meget fejlbehæftet, hvis du er ny til Python. Hvis du blander en naiv datetime og bevidst datetime, får du en fejl. Og Python har ikke indbygget timesone support, du skal bruge pyts, et modul til timesone information.

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

for at undgå denne slags problemer skal du sørge for, at dine datetime-objekter altid er offset-naive eller altid offset-Opmærksomme. Men vi kan ikke undgå at håndtere tid, så min bedste praksis er altid at arbejde med offset-bevidst datetime.

Python standard er naiv datetime. now() returnerer naiv datetime i din lokale timesone, og utcnow() returnerer også en naiv datetime, selv funktionen angiver allerede UTC-timesonen! Du skal bruge pytz modulet og også tzlocal modulet for at få tingene rigtigt. Nedenfor er hvordan jeg får tid med den rigtige tid.

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

Parsing datetime med timesone

opdatering: Dette er kun et problem i Python 2

en anden overraskelse er python strptime parser virker ikke med Timesone. Nedenstående kode vil bare mislykkes.

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

for at analysere datetime med timesone skal du bruge et andet modul python-dateutil. Dette modul giver en parser, der vil arbejde med tiden. Nu kan du analysere datetime med timesone!

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

Timedelta og DST

det sidste du skal være forsigtig, når du manipulerer offset-bevidst datetime. pytz vil hjælpe dig med at fortælle, om en dato er under DST indflydelse ved at kontrollere dst() metode.

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

Bemærk: DST for 2017 sluttede den 5.November. Så enhver dato efter Nov 5th vil have timedelta(0)

men dst() oplysningerne opdateres ikke, når du manipulerer datetime

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

hvad du virkelig kan gøre er at konvertere tilbage til naiv-offset datetime, og anvend derefter deltaet…

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

sammendrag

arbejde med Datetime i Python er fejlbehæftet. Det er fordi Python ikke understøtter godt datetime og timesone. Du bliver nødt til at bruge mange ekstra moduler. Men der er faktisk en sølvkugle, du kan bare bruge pil. Dette modul giver en erstatning for python datetime modul, og det er altid offset-bevidst, og det løser også alle problemer, som jeg nævner ovenfor. Det eneste, jeg kan være bekymret, er integrationen med andre eksterne applikationer som Spark.