2014-07-21 13 views
22

Próbuję zrozumieć dlaczego Dostaję te wyniki przy konwersji strefy czasowe UTC:nieoczekiwane wyniki konwersji strefy czasowe w Pythonie

In [74]: d1 = datetime(2007, 12, 5, 6, 30,tzinfo=pytz.timezone('US/Pacific')) 
In [75]: d1 
Out[75]: datetime.datetime(2007, 12, 5, 6, 30, tzinfo=<DstTzInfo 'US/Pacific' LMT-1 day, **16:07:00 STD**>) 
In [76]: d1.astimezone(pytz.utc) 
Out[76]: datetime.datetime(2007, 12, 5, 14, 23, tzinfo=<UTC>) 

Dlaczego 06:30 stać 14:23?

Z drugiej strony, jeśli mogę użyć następujące podejście, pojawia się oczekiwany wynik:

In [90]: d2 = datetime(2007, 12, 5, 6, 30) 
In [91]: uspac = pytz.timezone('US/Pacific') 
In [92]: d2_aware = uspac.localize(d2) 
In [94]: d2_aware.astimezone(pytz.utc) 
Out[94]: datetime.datetime(2007, 12, 5, 14, 30, tzinfo=<UTC>) 

Odpowiedz

18

Od częściowej dokumentacji: http://pytz.sourceforge.net/#localized-times-and-date-arithmetic

Niestety używając argumentu tzinfo standardowego konstruktorzy datetime „” nie działa”” z pytz dla wielu stref czasowych. [...] Jest bezpieczny dla stref czasowych bez zmian w świetle dziennym, takich jak UTC. [...] Preferowanym sposobem radzenia sobie z czasami jest zawsze praca w UTC, konwersja do czasu lokalnego tylko wtedy, gdy generowanie danych wyjściowych jest odczytywane przez ludzi.

+0

Dzięki! Nie mogłem tego rozgryźć dla mojego życia! – Inti

0

Drukuj d2_aware przed .astimezone i widzisz PST-1 (czasu pacyficznego), ale w pierwszym przykładzie masz LMT-1 (Lokalny średni czas) - i prawdopodobnie może dać 7-minutową różnicę.

Ale nie wiem, dlaczego pytz użyć różnych stref czasowych.

24

Co mam tylko obejście, prosta zasada jest Nigdy tworzyć datetime z informacją stref czasowych za pomocą datetime().

Ta próbka dałaby wskazówkę do tego. Jak widzisz, możesz uniknąć nieoczekiwanej różnicy, raz i tylko robisz "naiwny" datetime (to jest datetime bez informacji o strefie czasowej), a następnie lokalizujesz go (nie jest on stosowany, gdy tworzysz datetime w UTC):

import pytz 
from datetime import datetime 

# make Jan 1 on PDT -> UTC 
pdt = pytz.timezone("America/Los_Angeles") 
pdtnow1 = datetime(2014,1,1, tzinfo=pdt) 
pdtnow2 = pdt.localize(datetime(2014,1,1)) 
pytz.utc.normalize(pdtnow1) 
# > datetime.datetime(2014, 1, 1, 7, 53, tzinfo=<UTC>) 
pytz.utc.normalize(pdtnow2) 
# > datetime.datetime(2014, 1, 1, 8, 0, tzinfo=<UTC>) 

# make Jan 1 on UTC -> PDT 
utcnow1 = datetime(2014,1,1, tzinfo=pytz.utc) 
utcnow2 = pytz.utc.localize(datetime(2014,1,1)) 
pdt.normalize(utcnow1) 
# > datetime.datetime(2013, 12, 31, 16, 0, 
# > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>) 
pdt.normalize(utcnow2) 
# > datetime.datetime(2013, 12, 31, 16, 0, 
# > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>) 
+3

Myślałem, że tracę rozum, kiedy nie widziałem moich wyników przez kilka minut. Dziękuję bardzo za ten przykład. – punkrockpolly

+0

@punkrockpolly Moja przyjemność! – Kenial

+0

To szukanie w Internecie dla offsetu 7:53, które pomogło mi znaleźć to pytanie. Przypuszczam, że teraz, gdy zaczęły się letnie oszczędności na czas Pacyfiku, siedem minut jakoś zostało dodane do offsetu zamiast godziny? Jak dziwnie! –

3

Wracam do pytań o datę i godzinę, aby sprawdzić, czy niektóre nowsze biblioteki okażą się bardziej przydatne w takich sytuacjach (lub nie). pendulum to taki, który przechowuje strefę czasową z datą i godziną, co czyni ją szczególnie cenną w takich sytuacjach.

>>> import pendulum 
>>> d1 = pendulum.datetime(2007,12,5,6,30, tzinfo='US/Pacific') 
>>> d1 
<Pendulum [2007-12-05T06:30:00-08:00]> 
>>> d1.timezone 
<Timezone [US/Pacific]> 
>>> d1.astimezone(tz='UTC') 
<Pendulum [2007-12-05T14:30:00+00:00]> 

Wiele innych słodkich elementów.

Powiązane problemy