2017-09-02 74 views
0

正如你可以從下面的代碼片段看到的,兩種方法之間有一個小時的差異。是什麼原因 ?爲什麼datetime.utcnow()和datetime.now(timezone('UTC'))之間有區別?

from datetime import datetime 
from pytz import timezone 
import time 

def timestamp2date(timestamp): 
    # function converts a UTC timestamp into Europe/Zurich Gregorian date 
    DATE_TIME_FORMAT = "%Y-%m-%d %H:%M:%S" 
    utcTimeStamp = datetime.fromtimestamp(int(timestamp)).replace(tzinfo=timezone('UTC')) 
    return utcTimeStamp.astimezone(timezone('Europe/Zurich')).strftime(DATE_TIME_FORMAT) 

timeStampUTC_1 = time.mktime(datetime.utcnow().timetuple()) 
print(timeStampUTC_1) 
print(timestamp2date(timeStampUTC_1)) 
timeStampUTC_2 = time.mktime(datetime.now(timezone('UTC')).timetuple()) 
print(timeStampUTC_2) 
print(timestamp2date(timeStampUTC_2)) 
print(timeStampUTC_2 - timeStampUTC_1) 

# 1504385450.0 
# 2017-09-03 00:50:50 this the right time 
# 1504389050.0 
# 2017-09-03 01:50:50 
# 3600.0 
+0

我沒有在我的Windows 10筆記本電腦QPython NND我的Android智能手機,其執行的Python 3.2解釋器中運行的python 3.6的代碼,我獲得同樣的區別。我當地的時區是歐洲/蘇黎世。 –

+0

...但即使以美國/太平洋作爲時區,差異也是如此。 –

回答

1

的原因是,datetime.timetuple()dst=-1如果datetime沒有偏移量感知和dst=0 or 1當偏移量感知。

從文檔:

結果的tm_isdst標誌根據dst()方法設置:tzinfoNonedst()返回Nonetm_isdst設爲-1;否則,如果dst()返回非零值,則tm_isdst設置爲1;否則tm_isdst設置爲0

In []: 
datetime.utcnow() 
Out[]: 
datetime.datetime(2017, 9, 2, 23, 9, 12, 715042) 

In []: 
print(datetime.utcnow().dst()) 
Out[]: 
None 

In []: 
datetime.now(timezone('UTC')) 
Out[]: 
datetime.datetime(2017, 9, 2, 23, 9, 15, 856983, tzinfo=<UTC>) 

In []: 
datetime.now(timezone('UTC')).dst() 
Out[] 
datetime.timedelta(0) 

In []: 
datetime(2017, 9, 2, 23, 9, 15, 856983).timetuple() 
Out[]: 
time.struct_time(tm_year=2017, tm_mon=9, tm_mday=2, tm_hour=23, tm_min=9, 
       tm_sec=15, tm_wday=5, tm_yday=245, tm_isdst=-1) 
                  ^^ 
In []: 
datetime(2017, 9, 2, 23, 9, 15, 856983, timezone('UTC')).timetuple() 
Out[]: 
time.struct_time(tm_year=2017, tm_mon=9, tm_mday=2, tm_hour=23, tm_min=9, 
       tm_sec=15, tm_wday=5, tm_yday=245, tm_isdst=0) 
                  ^

這改變了timestamptime.mktime()生成因爲mktime對待-1未知,並且使用本地時間,所以可以計算dst=1,因此,它們可以是一個1小時不同(3600s):

In []: 
time.mktime(datetime(2017, 9, 2, 23, 9, 15, 856983).timetuple()) 
Out[]: 
1504411755.0 

In []: 
time.mktime(datetime(2017, 9, 2, 23, 9, 15, 856983, timezone('UTC')).timetuple()) 
Out[]: 
1504415355.0 
+0

從文檔:在調用mktime()時,夏令時有效時tm_isdst可能設置爲1,如果不是,則爲0。值爲-1表示這是未知的,並且通常會導致填充正確的狀態。 –

+0

@ Jean-PierreSchnyder mktime的文檔狀態爲:「它的參數是struct_time或完整的9元組(自dst標誌是必需的;如果它是未知的,則使用-1作爲dst標誌)表示當地時間的時間**,而不是UTC **。所以,如果你給它'-1',但你已經通過'UTC'時間,它會糾正'localtime',所以你得到的差異。 – AChampion

0

這裏的這是我進一步探索與夏令時標誌相關的時區概念的結果。代碼非常簡單。

總結的結果,有處理日期/時間信息的正確方法:

  1. 日期/時間對象必須本地化
  2. 如果正確本地化,日期/時間對象是否顯示正確的夏令時信息
  3. 將您的本地化日期/時間對象轉換爲根據定義的UTC日期/時間對象時會反映這一點DST不可知
  4. 當您訪問股票或貨幣歷史記錄時,所有這些考慮事項尤其相關CAL分鐘費率API

代碼:

from datetime import datetime 
from pytz import timezone 
import time 

print("---- Winter time (CET=Central European Time) ----") 
dateStr = "2014-02-28 22:28:15" 
datetimeObjUnlocalized = datetime.strptime(dateStr, "%Y-%m-%d %H:%M:%S") 
print('UNL: ' + datetimeObjUnlocalized.strftime("%Y-%m-%d %H:%M:%S %Z%z")) 
print('  datetimeObjUnlocalized-->tm_isdst=' + str(datetimeObjUnlocalized.timetuple()[8])) 
datetimeObjZH = timezone('Europe/Zurich').localize(datetimeObjUnlocalized) 
print('ZH: ' + datetimeObjZH.strftime("%Y-%m-%d %H:%M:%S %Z%z")) 
print('  datetimeObjZH-->tm_isdst=' + str(datetimeObjZH.timetuple()[8])) 
print("UTC: " + datetimeObjZH.astimezone(timezone('UTC')).strftime("%Y-%m-%d %H:%M:%S %Z%z")) 

print("\n---- Summer time (CEST=Central European Summer Time) ----") 
dateStr = "2014-06-28 22:28:15" 
datetimeObjUnlocalized = datetime.strptime(dateStr, "%Y-%m-%d %H:%M:%S") 
print('UNL: ' + datetimeObjUnlocalized.strftime("%Y-%m-%d %H:%M:%S %Z%z")) 
print('  datetimeObjUnlocalized-->tm_isdst=' + str(datetimeObjUnlocalized.timetuple()[8])) 
datetimeObjZH = timezone('Europe/Zurich').localize(datetimeObjUnlocalized) 
print('ZH: ' + datetimeObjZH.strftime("%Y-%m-%d %H:%M:%S %Z%z")) 
print('  datetimeObjZH-->tm_isdst=' + str(datetimeObjZH.timetuple()[8])) 
print("UTC: " + datetimeObjZH.astimezone(timezone('UTC')).strftime("%Y-%m-%d %H:%M:%S %Z%z")) 

Console output

相關問題