2016-04-01 101 views
3

假設我在請求中接收任意日期時間對象,就像這樣,它可能來自任何可能的時區 - 我不知道是哪一個。 例如起見,假裝它來自東海岸如何將日期時間從一個任意時區轉換爲另一個任意時區

import pytz 
from colander import iso8601 
... 
    ests1 = iso8601.parse_date('2016-04-01T00:00:00.0000-04:00') 

假裝ests1是進來

使用pytz的對象,我可以找出一些關於它的時區

etz = ests1.timetz() # 00:00:00-04:00 
    etzi = ests1.tzinfo # <FixedOffset '-04:00' datetime.timedelta(-1, 72000)> 
    etzn = ests1.tzname() # '-04:00' # EST 
    edst = ests1.dst() # '0:00:00' 

請注意,無論日期ests1是什麼 - dst()似乎總是返回相同的值

我想要這樣做:

psts1 = pytz.timezone(etzn 
        ).localize(dtime.datetime.fromtimestamp(ests1) 
        ).astimezone(pytz.timezone('US/Pacific')) 

但只是導致

UnknownTimeZoneError: '-04:00' 

我也試過這樣:

def convert_dt_to_pstz(dt): 
    pstoffset = -25200 # -7 * 60 * 60 - but what about DST? how do we tell which offset to use? -8 or -7 
    return dt.astimezone(tzoffset(None,pstoffset)) # convert to PST 

但隨着這個問題是我不知道如何判斷日期需求夏令時進行調整。

我也試過這樣:

utc_date = ests1.astimezone(pytz.utc) # 2016-04-01T04:00:00+00:00 
    ptz = pytz.timezone('US/Pacific') 
    new_date = utc_date.replace(tzinfo=ptz) # 2016-04-01T04:00:00-07:53 

但看看在NEW_DATE奇怪的結果:-07:53 ?

請注意,我不能使用對應於「現在」或服務器的位置的任何信息,因爲它可以在任何地方

+3

請注意純粹的數字偏移量不會提供夏令時是否生效的信息。您必須瞭解更多有關如何生成時間以便能夠推斷「-04:00」來自美國/東部時區而非來自巴西的信息。但是,這是一個細節 - 我認爲你的問題很有趣。答案的一部分是「從源時區轉換爲UTC;從UTC轉換爲目標時區「。那麼如何精確地完成這些轉換就成了問題。 –

+0

從iso8601格式,你不能告訴,它會說,-0400的EDT和-0500的EST,但-0400可能是AMT以及 – scope

+0

@scope:有,有辦法確定夏令時 - 但它是複雜的我想知道是否有一些已經建成的東西能夠完成這項工作。我還沒有找到它雖然 – slashdottir

回答

3

要一個時區感知datetime對象轉換爲不同的時區,use datetime.astimezone() method

pacific_time = ests1.astimezone(pytz.timezone('US/Pacific')) 

一般來說,pytz docs建議呼籲的結果pytz.timezone('US/Pacific').normalize(),但你不要在這裏需要它,因爲ests1時區有固定的UTC偏移量。

+0

似乎工作,謝謝你 – slashdottir

0

我想我猜中了這一次:

from datetime import datetime as dtime 
import pytz 
from colander import iso8601 

ests1 = iso8601.parse_date('2016-04-01T00:00:00.0000-04:00') 
epoch = dtime(1970, 1, 1, tzinfo=pytz.UTC)   # 1970-01-01T00:00:00+00:00 
ept = (ests1 - epoch).total_seconds()    # 1459483200.0 

utc_date = dtime.fromtimestamp(ept, tz=pytz.UTC) # 2016-04-01T04:00:00+00:00 
ptz = pytz.timezone('US/Pacific') 
pst_date = dtime.fromtimestamp(ept, tz=ptz)   # 2016-03-31T21:00:00-07:00 

ests2 = iso8601.parse_date('2016-02-01T00:00:00.0000-04:00') 
ept2 = (ests2 - epoch).total_seconds()    # 1454299200.00 

utc_date2 = dtime.fromtimestamp(ept2, tz=pytz.UTC) # 2016-02-01T04:00:00+00:00 
pst_date2 = dtime.fromtimestamp(ept2, tz=ptz)  # 2016-01-31T20:00:00-08:00 

如此,它似乎是越簡單

def convert_to_tz(dt,tz_new): 
    seconds = (dt - epoch).total_seconds() 
    return dtime.fromtimestamp(seconds, tz=tz_new) 
相關問題