pytz utc преобразуване

Какъв е правилният начин за преобразуване на наивно време и tzinfo в UTC време? Кажете, че имам:

d = datetime(2009, 8, 31, 22, 30, 30)
tz = timezone('US/Pacific')

Първи начин, вдъхновен от pytz:

d_tz = tz.normalize(tz.localize(d))
utc = pytz.timezone('UTC')
d_utc = d_tz.astimezone(utc)

Втори начин, от UTCDateTimeField

def utc_from_localtime(dt, tz):
    dt = dt.replace(tzinfo=tz)
    _dt = tz.normalize(dt)
    if dt.tzinfo != _dt.tzinfo:
        # Houston, we have a problem...
        # find out which one has a dst offset
        if _dt.tzinfo.dst(_dt):
            _dt -= _dt.tzinfo.dst(_dt)
        else:
            _dt += dt.tzinfo.dst(dt)
    return _dt.astimezone(pytz.utc)

Излишно е да казвам, че тези два метода дават различни резултати за доста часови зони.

Въпросът е - кой е правилният път?


person Art    schedule 31.08.2009    source източник
comment
Изумен съм, че никой не е изтрил „Благодаря“ от основната част на въпроса. Да видим колко време ще отнеме да го премахнем!   -  person Art    schedule 01.12.2011
comment
По мои изчисления само 897 дни.   -  person    schedule 14.02.2012
comment
Благодаря ти, Уил, че поправи грешката!   -  person Art    schedule 15.02.2012


Отговори (4)


Вашият първи метод изглежда е одобрен и трябва да поддържа DST.

Можете да го съкратите малко, тъй като pytz.utc = pytz.timezone('UTC'), но вие вече го знаехте :)

tz = timezone('US/Pacific')
def toUTC(d):
    return tz.normalize(tz.localize(d)).astimezone(pytz.utc)

print "Test: ", datetime.datetime.utcnow(), " = ", toUTC(datetime.datetime.now())
person ewall    schedule 31.08.2009
comment
Защо normalize()? наистина ли е необходимо? - person kolypto; 31.01.2014
comment
@kolypto: Очевидно tz.normalize() ще отчита лятното часово време и други неудобства, които tz.localize() не прави, както е обяснено в други отговори на SO като този. - person ewall; 09.07.2014
comment
@kolypto: някои местни времена не съществуват, например, когато местният часовник скача напред през пролетта по време на прехода към лятно време в някои страни (северното полукълбо). tz.localize() зачита дадения d обект (той не променя часа, а само се опитва да добави подходящ tzinfo обект), следователно tz.normalize() е необходим за коригиране на несъществуващи часове. Въпреки че и двете времена (преди/след корекцията) трябва да съответстват на едно и също UTC време, т.е. tz.normalize() може да е ненужно, ако всичко, което правим, е да конвертираме времето в UTC, както в този случай. - person jfs; 04.10.2014

Какъв е правилният начин за преобразуване на наивно време и tzinfo в utc време?

Този отговор изброява някои проблеми с преобразуването на местно време в UTC:

from datetime import datetime
import pytz # $ pip install pytz

d = datetime(2009, 8, 31, 22, 30, 30)
tz = pytz.timezone('US/Pacific')

# a) raise exception for non-existent or ambiguous times
aware_d = tz.localize(d, is_dst=None)
## b) assume standard time, adjust non-existent times
#aware_d = tz.normalize(tz.localize(d, is_dst=False))
## c) assume DST is in effect, adjust non-existent times
#aware_d = tz.normalize(tz.localize(naive_d, is_dst=True))

# convert to UTC
utc_d = aware_d.astimezone(pytz.utc)
person jfs    schedule 04.10.2014
comment
Предпочитам това решение, тъй като включва подробности за опцията DST. - person Darren Weber; 07.06.2018

Използвайте първия метод. Няма причина да преоткривате колелото на преобразуването на часовите зони

person Jon W    schedule 31.08.2009

person    schedule
comment
не е правилно. Ако USE_TZ=True тогава timezone.now() връща осъзната дата и час в UTC и следователно не трябва да извиквате tz.normalize() на него. Ако USE_TZ=False тогава django използва часова зона по подразбиране, която може да е различна от Америка/Лос_Анджелис и кодът е грешен и в този случай. - person jfs; 24.07.2015