2015-04-08 94 views
2

我使用pytz做日期時間轉換,但在約8AM EST DST活動的情況下,pytz顯示意外的數據。使用pytz python時區轉換問題

eight_35 = datetime.now(pytz.timezone('US/Eastern')) # assume today's 8:35AM EST 
eight_am = datetime(eight_35.year, eight_35.month, eight_35.day, 8, 0, 0, 0, tzinfo=pytz.timezone('US/Eastern')) 

我注意到雖然這eight_35tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>eight_amtzinfo=<DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>,我不知道哪一個是正確的。

如果我這樣做轉換爲UTC,我得到如下結果:

eight_35.astimezone(pytz.utc) >>> 12:35PM UTC 
eight_am.astimezone(pytz.utc) >>> 12:56PM UTC 

我的代碼理應檢查,如果用戶在任何比美國東部時間上午8點大於已經登錄。創建查詢集時,Django會自動轉換爲UTC。

UserLoginLog.objects.create(user=user, date_login=now) date logged is 12:35PM UTC 

# this will result in no items because eight_am is translated as 12:56PM 
UserLoginLog.objects.filter(user=user, date_login__gte=eight_am) 

正如你可以看到,用戶登錄8:35所以如果我以後所有的日誌早上8點 什麼是對付它,所以我可以檢測到夏令時,但仍然能夠精確地比較數據的最佳方式?

+3

您可能會發現[本地時間問題](http://pytz.sourceforge.net/#problems-with-localtime)有幫助;它解釋了爲什麼直接指定'tzinfo'有時不起作用,以及如何使用'localize'解決問題。 – unutbu

+1

您需要本地化或標準化日期時間。只是因爲當你有一個天真的日期時間和應用時區時,目前沒有有關夏令時的信息。通常,從本地'datetime'到UTC的轉換可能有兩個結果。所以,正如@unutbu所說的那樣,在將時區應用到樸素的datetime時只使用'localize'。 –

回答

2
  • datetime.now(pytz.timezone('US/Eastern')) - 正確
  • datetime(..same time.., tzinfo=pytz.timezone('US/Eastern')) - 不正確

this answer爲什麼你不應該使用tzinfo參數與可能在不同的時間不同的UTC偏移pytz時區。

.now(tz)內部使用UTC時間(tz.fromutc(utc_time)),因此它允許時區選擇對應於給定時間的正確的utc偏移量。

如果您更改了知道的日期時間對象(以便生成的時間可能具有不同的utc偏移量),則應該調用dt = tz.normalize(dt)以獲取正確的tzinfo。見Localized times and date arithmetic

0

你們都很有幫助!所以我所做的就是做出類似

@staticmethod 
def est_localize(datetime_object): 
    # remove tzinfo 
    new_datetime = datetime_object.replace(tzinfo=None) 
    # finally, localize the datetime 
    new_datetime = pytz.timezone('US/Eastern').localize(new_datetime) 
    return new_datetime 

和我創建的每一個datetime對象,我將它們包裝裏面所有est_localize(),包括那些在那裏我必須使用+timedelta()+relativedelta()。只要我將它們包裝在est_localize()內,所有翻譯都是正確的。謝謝大家!

eight_35 = datetime.now(pytz.timezone('US/Eastern')) # assume today's 8:35AM EST 
eight_am = est_localize(datetime(eight_35.year, eight_35.month, eight_35.day, 8))