Časové pásmo je těžký problém. DST je ještě těžší problém. Když jsem začal správně používat datetime v Pythonu, zjistil jsem, že chodím do problémů a problémů. Rozhodl jsem se tedy napsat blog, abych se podělil o své zkušenosti.

„naivní“a“ Aware “

první věc, kterou je třeba vědět, je, že v Pythonu existují dva typy datetime: offset-naive a offset-aware. Offset naive znamená, že datetime nemá informace o časovém pásmu. Mohlo by to být velmi náchylné k chybám, pokud jste v Pythonu noví. Pokud smícháte naivní datetime a aware datetime, dostanete chybu. A Python nemá vestavěnou podporu časového pásma, musíte použít pytz, modul pro informace o časovém pásmu.

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

Chcete-li se tomuto problému vyhnout, musíte se ujistit, že vaše objekty datetime jsou vždy offset-naivní nebo vždy offset-aware. Ale nemůžeme se vyhnout jednání s časovým pásmem, takže moje nejlepší praxe je vždy pracovat s offset-aware datetime.

výchozí Python je naivní datetime. now() vrátí naivní datetime v místním časovém pásmu a utcnow() také vrátí naivní datetime, dokonce i funkce již označuje Časové pásmo UTC! Budete potřebovat modul pytz a také modul tzlocal, abyste věci napravili. Níže je uvedeno, jak dostanu čas se správným časovým pásmem.

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

parsování datetime s časovým pásmem

aktualizace: Toto je pouze problém v Pythonu 2

dalším překvapením je python strptime parser nepracuje s časovým pásmem. Níže uvedený kód prostě selže.

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

Chcete-li analyzovat datetime s časovým pásmem, budete potřebovat další modul python-dateutil . Tento modul poskytuje analyzátor, který bude pracovat s časovým pásmem. Nyní můžete analyzovat datetime s časovým pásmem!

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

Timedelta a DST

poslední věc, kterou musíte být opatrní při manipulaci s offset-aware datetime. pytz vám pomůže zjistit, zda je datum pod vlivem DST kontrolou metody 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)

Poznámka: DST pro rok 2017 skončila 5. Listopadu. Takže jakékoli datum po listopadu 5th bude mít timedelta(0)

ale informace dst() nejsou aktualizovány, když manipulujete s datetime

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

co můžete opravdu udělat, je převést zpět na naivní posun datetime, pak použijte delta…

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

shrnutí

práce s Datetime v Pythonu je náchylná k chybám. Je to proto, že Python nepodporuje dobře datetime a Časové pásmo. Budete muset použít mnoho dalších modulů. Nicméně, tam je vlastně Stříbrná kulka, stačí použít arrow. Tento modul poskytuje náhradu za python datetime modulu, a to je vždy offset-aware,a to také řeší všechny problémy, které jsem zmínil výše. Jediná věc, kterou se mohu obávat, je integrace s jinými externími aplikacemi, jako je Spark.