1、時間戳的概念
時間戳的定義請看百科unix時間戳,需要注意的時間戳為當前時刻減去UTC時間(1970.1.1)零點時刻的秒數差,與當前系統所處的時區無關,同一時刻不管在任何時區下得到的時間戳都是一樣的。
最近因為存儲數據庫需要將時間轉為時間戳的字節型來存儲,用了python datetime模塊,期間遇到一些問題,現在終於弄懂了時間戳、時間和UTC時間的正確轉換關系,總結以下供大家參考。
2、python datatime模塊實現時間戳和本地時間、UTC時間之間的互相轉化
1) 獲得unix timestamp
dt=datetime.datetime.now() #獲取本地當前時間
dt.timestamp() #獲取時間戳
注:
- 此方式下now()函數中有個參數為tz,參數意思為時區信息,不設時為本地時間,當設置時,如tz=timezone.utc,則表示為當前的utc時間,無論是utc時間還是本地時間,獲得的時間戳都是同一個值.
- timestamp()內部會根據時區設置得到時間戳,當時區為utc時間時timestamp()函數直接減去EPOCH得到的秒數,當為其他時區的時間時通過標准C庫函數mktime得到相差秒數,不管哪種方式,相差的秒數差是一樣的,所以不同時區下的時間戳必定為同一個值。
2) python datetime模塊的小坑
由1)的闡述得到python在不同時區下都能獲得時間戳,我就采用了utc時間獲得時間戳,datetime有兩種方式獲得utc時間:
方式一:
dt=datetime.datetime.now(timezone.utc) #類型為aware datetime object,時區為utc
dt.timestamp() #通過減去EPOCH得到時間戳
方式二:
dt=datetime.datetime.utcnow() #類型為naive datetime object,不包含時區信息
dt.timestamp() #通過mktime得到時間戳(得到的時間戳是錯誤的
- 在未理解naive和aware之前,以為兩種方式獲得時間戳都是一樣的,未曾想第二種方式下再通過timestamp()獲得的時間戳是錯誤的,為什么會發生這種情況,是因為naive是不含時區的類型,而aware是有時區類型。
- 第二種雖然和方式一獲得的值是相同的,但是第二種方式不包含時區信息,在方式二下執行dt.timestamp(),timestamp()默認tz=None,即為本地時區,這樣就會按照mktime得到秒數差,但其實此時dt卻是utc時間。而方式一有時區信息,執行dt.timestamp()是直接減去EPOCH時間。
- 當時間值相同時,naive類型和aware類型時間下執行timestamp()結果是不一樣的,一定要注意,不能踩了這個坑,除非是本地時間,如果想通過其他時區的時間通過timestamp()得到時間戳,一定要帶有時區信息。
3) 通過timestamp得出datetime和utc datetime
-
timestamp轉datetime
datetime.datetime.fromtimestamp(timestamp) #獲得本地時間,類型naive datetime obiect
-
timestamp轉utc datetime
兩種方式獲得utc時間,但datetime object類型不一樣。
方式一:
datetime.datetime.utcfromtimestamp(timestamp) #類型naive datetime object
方式二:
datetime.datetime.fromtimestamp(timestamp,timezone.utc) #類型aware datetime object。
3、總結:
- timestamp沒有時區之分,不要認為不同時區有不同的時間戳。
- datetime object有兩種類型,naive是不含時區的類型,而aware是有時區類型,就算顯示的值一樣,不同類型的object也不能直接進行數學運算。