淺談Python3中datetime不同時(shí)區(qū)轉(zhuǎn)換介紹與踩坑_第1頁(yè)
淺談Python3中datetime不同時(shí)區(qū)轉(zhuǎn)換介紹與踩坑_第2頁(yè)
淺談Python3中datetime不同時(shí)區(qū)轉(zhuǎn)換介紹與踩坑_第3頁(yè)
淺談Python3中datetime不同時(shí)區(qū)轉(zhuǎn)換介紹與踩坑_第4頁(yè)
淺談Python3中datetime不同時(shí)區(qū)轉(zhuǎn)換介紹與踩坑_第5頁(yè)
已閱讀5頁(yè),還剩1頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第淺談Python3中datetime不同時(shí)區(qū)轉(zhuǎn)換介紹與踩坑最近的項(xiàng)目需要根據(jù)用戶所屬時(shí)區(qū)制定一些特定策略,學(xué)習(xí)、應(yīng)用了若干python3的時(shí)區(qū)轉(zhuǎn)換相關(guān)知識(shí),這里整理一部分記錄下來(lái)。

下面涉及的幾個(gè)概念及知識(shí)點(diǎn):

GMT時(shí)間:GreenwichMeanTime,格林尼治平均時(shí)間

UTC時(shí)間:UniversalTimeCoordinated世界協(xié)調(diào)時(shí),可以認(rèn)為是更精準(zhǔn)的GMT時(shí)間,但兩者誤差極小,在1s以內(nèi),一般可視為等同

LMT:LocalMeanTime,當(dāng)?shù)貥?biāo)準(zhǔn)時(shí)間

Python中的北京時(shí)間:Python的標(biāo)準(zhǔn)timezone中信息中并沒(méi)有Asia/Beijing,原因要追溯到國(guó)民政府期間上報(bào)給國(guó)際標(biāo)準(zhǔn)的五個(gè)時(shí)區(qū)城市沒(méi)有北京,因此一般使用Asia/Shanghai獲取東8區(qū)時(shí)間

Python使用到的時(shí)間相關(guān)函數(shù)及概念:

包含時(shí)區(qū)信息的datetime稱為:offset-awaredatetime,反之稱為offset-naivedatetime

pytz.timezone(x):pytzpackage中預(yù)定義的時(shí)區(qū)相關(guān)對(duì)象,pytz可通過(guò)python3-mpipinstallpytz安裝

datetime(...):直接指定year/month/day/hour/second生成naivedatetime

datetime(...tzinfo=tz):直接指定year/month/day/hour/second+時(shí)區(qū)信息生成offset-awaredatetime

datetime.now():生成當(dāng)前默認(rèn)時(shí)區(qū)的naivedatetime

datetime.now(tzinfo=tz):生成指定時(shí)區(qū)的offset-awaredatetime

datetime.strptime(string,format):生成當(dāng)前默認(rèn)時(shí)區(qū)的string、format表示的naivedatetime

datetime.replace(tzinfo=tz):直接替換datetime時(shí)區(qū)信息為tz時(shí)區(qū)offset-awaredatetime--不針對(duì)時(shí)區(qū)進(jìn)行任何轉(zhuǎn)換

datetime.astimezone(tz):將時(shí)間轉(zhuǎn)換為新的tz時(shí)區(qū)的offset-awaredatetime

下述代碼示例中,由于云主機(jī)位于日本,所以默認(rèn)時(shí)區(qū)為東9區(qū)(Asia/Tokyo)

Python中獲取當(dāng)前時(shí)刻時(shí)間:

In[1]:importpytz

In[2]:fromdatetimeimportdatetime,timedelta

In[3]:datetime.now()#默認(rèn)時(shí)區(qū)當(dāng)前時(shí)間

Out[3]:datetime.datetime(2025,8,1,18,36,8,352873)

In[4]:datetime.now(pytz.timezone('Asia/Tokyo'))#指定Tokyo時(shí)區(qū)當(dāng)前時(shí)間

Out[4]:datetime.datetime(2025,8,1,18,36,25,421048,tzinfo=DstTzInfo'Asia/Tokyo'JST+9:00:00STD)

可以看到,datetime.now()未指定時(shí)區(qū)時(shí),獲取到的對(duì)象是offset-naviedatetime,而指定時(shí)區(qū)后則是offset-awaredatetime,naive和aware的datetime是不可以執(zhí)行比較、相減相關(guān)操作的,只有同類型的datetime才能求時(shí)間差值、比較大小,如下:

In[5]:datetime.now()-datetime.now(pytz.timezone('Asia/Tokyo'))

---------------------------------------------------------------------------

TypeErrorTraceback(mostrecentcalllast)

ipython-input-5-8b6c111dc5deinmodule

----1datetime.now()-datetime.now(pytz.timezone('Asia/Tokyo'))

TypeError:can'tsubtractoffset-naiveandoffset-awaredatetimes

In[6]:datetime.now()-datetime.now()#只有同樣的offset-naivedatetime才能求差值

Out[6]:datetime.timedelta(days=-1,seconds=86399,microseconds=999991)

In[8]:datetime.now(pytz.timezone('Asia/Tokyo'))-datetime.now(pytz.timezone('Asia/Tokyo'))#同樣的offset-awaredatetime才能求差值

Out[8]:datetime.timedelta(days=-1,seconds=86399,microseconds=999976)

這里碰到了第一個(gè)坑,比如我們想獲得北京時(shí)間2025年1月1日0點(diǎn)的datetime,然后將其轉(zhuǎn)換為東京時(shí)間,直覺(jué)上我們很可能這么寫:

In[19]:datetime(2025,1,1,tzinfo=pytz.timezone('Asia/Shanghai'))#這里獲取北京時(shí)間202501010點(diǎn)的datetime

Out[19]:datetime.datetime(2025,1,1,0,0,tzinfo=DstTzInfo'Asia/Shanghai'LMT+8:06:00STD)#注意獲取的是LMT時(shí)間

In[21]:datetime(2025,1,1,tzinfo=pytz.timezone('Asia/Shanghai')).astimezone(pytz.timezone('Asia/Tokyo'))#將北京時(shí)轉(zhuǎn)換為東京時(shí)間

Out[21]:datetime.datetime(2025,1,1,0,54,tzinfo=DstTzInfo'Asia/Tokyo'JST+9:00:00STD)#獲取的是日本標(biāo)準(zhǔn)時(shí)間JST+9

In[22]:datetime.now(pytz.timezone('Asia/Shanghai'))#示例獲取當(dāng)前時(shí)刻北京時(shí)間

Out[22]:datetime.datetime(2025,8,1,18,11,6,706727,tzinfo=DstTzInfo'Asia/Shanghai'CST+8:00:00STD)#獲取的是中國(guó)標(biāo)準(zhǔn)時(shí)間(CST+8)

仔細(xì)一看,北京時(shí)間的0點(diǎn)轉(zhuǎn)化為東京時(shí)間卻是0:54,相差是54分鐘,而不是1個(gè)小時(shí),這就奇怪了,仔細(xì)一看tzinfo中的信息是LMT+8:06:00STD,表示這是LMT時(shí)間,相比UTC快8小時(shí)6分鐘,而不是東8區(qū)標(biāo)準(zhǔn)時(shí)間,而通過(guò)astimezone方法轉(zhuǎn)換后得到的就是日本標(biāo)準(zhǔn)時(shí)間(東9區(qū)),所以兩者之前的差值并不是1小時(shí)整。

第一個(gè)坑究其原因,通過(guò)datetime(..tzinfo=..)指定時(shí)區(qū)獲取的是LMT,而datetime.now(tz)、datetime.astimezone(tz)獲取的卻是UTC(GMT)標(biāo)準(zhǔn)時(shí)間,LMT和GMT標(biāo)準(zhǔn)時(shí)間可能會(huì)有甚至十分鐘級(jí)的差值,這已經(jīng)足夠影響到程序的正常邏輯了。

所以如果要保證獲取標(biāo)準(zhǔn)時(shí)區(qū)的時(shí)間,建議避免使用Asia/Shanghai、Asia/Tokyo這類大洲/城市字符串表示時(shí)間,而使用GMT、UTC這些無(wú)歧義的標(biāo)準(zhǔn)時(shí)區(qū),如下:

In[45]:datetime(2025,1,1,tzinfo=pytz.timezone('Etc/GMT-9'))

Out[45]:datetime.datetime(2025,1,1,0,0,tzinfo=StaticTzInfo'Etc/GMT-9')#東9區(qū)應(yīng)使用GMT-9

這里第二個(gè)坑出現(xiàn)了,由于歷史原因,Python中timezone的表示中,時(shí)區(qū)偏移以西為正,以東為負(fù),和我們熟悉的ISO標(biāo)準(zhǔn)剛好相反,所以東9區(qū)應(yīng)該表示為Etc/GMT-9,而Etc/GMT+9表示的其實(shí)是西9區(qū),如下可以驗(yàn)證GMT-9與JST相差0,GMT+9與JST相差18小時(shí)(64800s):

In[50]:datetime(2025,1,1,tzinfo=pytz.timezone('Etc/GMT-9'))-datetime(2025,1,1).astimezone(pytz.timezone('Asia/Tokyo'))

Out[50]:datetime.timedelta(0)

In[51]:datetime(2025,1,1,tzinfo=pytz.timezone('Etc/GMT+9'))-datetime(2025,1,1).astimezone(pytz.timezone('Asia/Tokyo'))

Out[51]:datetime.timedelta(seconds=64800)

最后,獲取指定時(shí)區(qū)2025年1月1日datetime的方式,以北京時(shí)間為例:

In[56]:datetime(2025,1,1,tzinfo=pytz.timezone('Etc/GMT-8'))

Out[56]:datetime.datetime(2025,1,1,0,0,tzinfo=StaticTzInfo'Etc/GMT-8')

In[58]:datetime(2025,1,1,tzinfo=pytz.timezone('Etc/GMT-8')).astimezone(pytz.timezone('Asia/Shanghai'))

Out[58]:datetime.datetime(2025,1,1,0,0,tzinfo=DstTzInfo'Asia/Shanghai'CST+8:00:00STD)#可見(jiàn)GMT-8和東八區(qū)標(biāo)準(zhǔn)時(shí)間(CST+8)一致

進(jìn)一步如果要獲取指定時(shí)區(qū)零點(diǎn)的時(shí)間戳就很簡(jiǎn)單了:

In[44]:datetime(2025,1,1,tzinfo=pytz.timezone('Etc/GMT0')).timestamp()#獲取格林尼治時(shí)區(qū)2025年1月1日0點(diǎn)時(shí)間戳

Out[44]:1609459200.0

另外兩種獲取指定時(shí)區(qū)時(shí)刻的方法,此三種方式彼此等價(jià):

In[51]:datetime(2025,1,1,tzinfo=pytz.t

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論