zoneinfo
--- IANA 時區(qū)支持?
3.9 新版功能.
zoneinfo
模塊根據(jù) PEP 615 的最初說明提供了具體的時區(qū)實現(xiàn)來支持 IANA 時區(qū)數(shù)據(jù)庫。 按照默認設(shè)置,zoneinfo
會在可能的情況下使用系統(tǒng)的時區(qū)數(shù)據(jù);如果系統(tǒng)時區(qū)數(shù)據(jù)不可用,該庫將回退為使用 PyPI 上提供的 tzdata 第一方包。
參見
使用 ZoneInfo
?
ZoneInfo
是 datetime.tzinfo
抽象基類的具體實現(xiàn),其目標是通過構(gòu)造器、 datetime.replace
方法或 datetime.astimezone
來與 tzinfo
建立關(guān)聯(lián):
>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime, timedelta
>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-10-31 12:00:00-07:00
>>> dt.tzname()
'PDT'
以此方式構(gòu)造的日期時間對象可兼容日期時間運算并可在無需進一步干預(yù)的情況下處理夏令時轉(zhuǎn)換:
>>> dt_add = dt + timedelta(days=1)
>>> print(dt_add)
2020-11-01 12:00:00-08:00
>>> dt_add.tzname()
'PST'
這些時區(qū)還支持在 PEP 495 中引入的 fold
。 在可能導(dǎo)致時間歧義的時差轉(zhuǎn)換中(例如夏令時到標準時的轉(zhuǎn)換),當 fold=0
時會使用轉(zhuǎn)換 之前 的時差,而當 fold=1
時則使用轉(zhuǎn)換 之后 的時差,例如:
>>> dt = datetime(2020, 11, 1, 1, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-11-01 01:00:00-07:00
>>> print(dt.replace(fold=1))
2020-11-01 01:00:00-08:00
當執(zhí)行來自另一時區(qū)的轉(zhuǎn)換時,fold 將被設(shè)置為正確的值:
>>> from datetime import timezone
>>> LOS_ANGELES = ZoneInfo("America/Los_Angeles")
>>> dt_utc = datetime(2020, 11, 1, 8, tzinfo=timezone.utc)
>>> # Before the PDT -> PST transition
>>> print(dt_utc.astimezone(LOS_ANGELES))
2020-11-01 01:00:00-07:00
>>> # After the PDT -> PST transition
>>> print((dt_utc + timedelta(hours=1)).astimezone(LOS_ANGELES))
2020-11-01 01:00:00-08:00
數(shù)據(jù)源?
zoneinfo
模塊不直接提供時區(qū)數(shù)據(jù),而是在可能的情況下從系統(tǒng)時區(qū)數(shù)據(jù)庫或 PyPI 上的第一方包 tzdata 獲取時區(qū)信息。 某些系統(tǒng),重要的一點是 Windows 系統(tǒng)也包括在內(nèi),并沒有可用的 IANA 數(shù)據(jù)庫,因此對于要保證獲取時區(qū)信息的跨平臺兼容性的項目,推薦對 tzdata 聲明依賴。 如果系統(tǒng)數(shù)據(jù)和 tzdata 均不可用,則所有對 ZoneInfo
的調(diào)用都將引發(fā) ZoneInfoNotFoundError
。
配置數(shù)據(jù)源?
當 ZoneInfo(key)
被調(diào)用時,此構(gòu)造器首先會在 TZPATH
所指定的目錄下搜索匹配 key
的文件,失敗時則會在 tzdata 包中查找匹配。 此行為可通過三種方式來配置:
TZPATH
可使用 環(huán)境變量 進行配置。在 運行時,搜索路徑可使用
reset_tzpath()
函數(shù)來修改。
編譯時配置?
默認的 TZPATH
包括一些時區(qū)數(shù)據(jù)庫的通用部署位置(Windows 除外,該系統(tǒng)沒有時區(qū)數(shù)據(jù)的“通用”位置)。 在 POSIX 系統(tǒng)中,下游分發(fā)者和從源碼編譯 Python 的開發(fā)者知道系統(tǒng)時區(qū)數(shù)據(jù)部署位置,它們可以通過指定編譯時選項 TZPATH
(或者更常見的是通過 配置旗標 --with-tzpath
) 來改變默認的時區(qū)路徑,該選項應(yīng)當是一個由 os.pathsep
分隔的字符串。
在所有平臺上,配置值會在 sysconfig.get_config_var()
中以 TZPATH
鍵的形式提供。
環(huán)境配置?
當初始化 TZPATH
時(在導(dǎo)入時或不帶參數(shù)調(diào)用 reset_tzpath()
時),zoneinfo
模塊將使用環(huán)境變量 PYTHONTZPATH
,如果變量存在則會設(shè)置搜索路徑。
- PYTHONTZPATH?
這是一個以
os.pathsep
分隔的字符串,其中包含要使用的時區(qū)搜索路徑。 它必須僅由絕對路徑而非相對路徑組成。 在PYTHONTZPATH
中指定的相對路徑部分將不會被使用,但在其他情況下當指定相對路徑時的行為該實現(xiàn)是有定義的;CPython 將引發(fā)InvalidTZPathWarning
,而其他實現(xiàn)可自由地忽略錯誤部分或是引發(fā)異常。
要設(shè)置讓系統(tǒng)忽略系統(tǒng)數(shù)據(jù)并改用 tzdata 包,請設(shè)置 PYTHONTZPATH=""
。
運行時配置?
TZ 搜索路徑也可在運行時使用 reset_tzpath()
函數(shù)來配置。 通常并不建議如此操作,不過在需要使用指定時區(qū)路徑(或者需要禁止訪問系統(tǒng)時區(qū))的測試函數(shù)中使用它則是合理的。
ZoneInfo
類?
- class zoneinfo.ZoneInfo(key)?
一個具體的
datetime.tzinfo
子類,它代表一個由字符串key
所指定的 IANA 時區(qū)。 對主構(gòu)造器的調(diào)用將總是返回可進行標識比較的對象;但是另一種方式,對所有的key
值通過ZoneInfo.clear_cache()
禁止緩存失效,對以下斷言將總是為真值:a = ZoneInfo(key) b = ZoneInfo(key) assert a is b
key
必須采用相對的標準化 POSIX 路徑的形式,其中沒有對上一層級的引用。 如果傳入了不合要求的鍵則構(gòu)造器將引發(fā)ValueError
。如果沒有找到匹配
key
的文件,構(gòu)造器將引發(fā)ZoneInfoNotFoundError
。
ZoneInfo
類具有兩個替代構(gòu)造器:
- classmethod ZoneInfo.from_file(fobj, /, key=None)?
基于一個返回字節(jié)串的文件類對象(例如一個以二進制模式打開的文件或是一個
io.BytesIO
對象)構(gòu)造ZoneInfo
對象。 不同于主構(gòu)造器,此構(gòu)造器總是會構(gòu)造一個新對象。key
形參設(shè)置時區(qū)名稱以供__str__()
和__repr__()
使用。由此構(gòu)造器創(chuàng)建的對象不可被封存 (參見 pickling)。
- classmethod ZoneInfo.no_cache(key)?
一個繞過構(gòu)造器緩存的替代構(gòu)造器。 它與主構(gòu)造器很相似,但每次調(diào)用都會返回一個新對象。 此構(gòu)造器在進行測試或演示時最為適用,但它也可以被用來創(chuàng)建具有不同緩存失效策略的系統(tǒng)。
由此構(gòu)造器創(chuàng)建的對象在被解封時也會繞過反序列化進程的緩存。
小心
使用此構(gòu)造器可以會以令人驚訝的方式改變?nèi)掌跁r間對象的語義,只有在你確定你的需求時才使用它。
也可以使用以下的類方法:
- classmethod ZoneInfo.clear_cache(*, only_keys=None)?
一個可在
ZoneInfo
類上禁用緩存的方法。 如果不傳入?yún)?shù),則會禁用所有緩存并且下次對每個鍵調(diào)用主構(gòu)造器將返回一個新實例。如果將一個鍵名稱的可迭代對象傳給
only_keys
形參,則將只有指定的鍵會被從緩存中移除。 傳給only_keys
但在緩存中找不到的鍵會被忽略。警告
發(fā)起調(diào)用此函數(shù)可能會以令人驚訝的方式改變使用
ZoneInfo
的日期時間對象的語義;這會修改進程范圍內(nèi)的全局狀態(tài)并因此可能產(chǎn)生大范圍的影響。 只有在你確定你的需求時才使用它。
該類具有一個屬性:
- ZoneInfo.key?
這是一個只讀的 attribute,它返回傳給構(gòu)造器的
key
的值,該值應(yīng)為一個 IANA 時區(qū)數(shù)據(jù)庫的查找鍵 (例如America/New_York
,Europe/Paris
或Asia/Tokyo
)。對于不指定
key
形參而是基于文件構(gòu)造時區(qū),該屬性將設(shè)為None
。備注
盡管將這些信息暴露給最終用戶是一種比較普通的做法,但是這些值被設(shè)計作為代表相關(guān)時區(qū)的主鍵而不一定是面向用戶的元素。 CLDR (Unicode 通用區(qū)域數(shù)據(jù)存儲庫) 之類的項目可被用來根據(jù)這些鍵獲取更為用戶友好的字符串。
字符串表示?
當在 ZoneInfo
對象上調(diào)用 str
時返回的字符串表示默認會使用 ZoneInfo.key
屬性(參見該屬性文檔中的用法注釋):
>>> zone = ZoneInfo("Pacific/Kwajalein")
>>> str(zone)
'Pacific/Kwajalein'
>>> dt = datetime(2020, 4, 1, 3, 15, tzinfo=zone)
>>> f"{dt.isoformat()} [{dt.tzinfo}]"
'2020-04-01T03:15:00+12:00 [Pacific/Kwajalein]'
對于基于文件而非指定 key
形參所構(gòu)建的對象,str
會回退為調(diào)用 repr()
。 ZoneInfo
的 repr
是由具體實現(xiàn)定義的并且不一定會在不同版本間保持穩(wěn)定,但它保證不會是一個有效的 ZoneInfo
鍵。
封存序列化?
ZoneInfo
對象的序列化是基于鍵的,而不是序列化所有過渡數(shù)據(jù),并且基于文件構(gòu)造的 ZoneInfo
對象(即使是指定了 key
值的對象)不能被封存。
ZoneInfo
文件的行為取決于它的構(gòu)造方式:
ZoneInfo(key)
: 當使用主構(gòu)造器構(gòu)造時,會基于鍵序列化一個ZoneInfo
對象,而當反序列化時,反序列化過程會使用主構(gòu)造器,因此預(yù)期它們與其他對同一時區(qū)的引用會是同一對象。 例如,如果europe_berlin_pkl
是一個包含基于ZoneInfo("Europe/Berlin")
構(gòu)建的封存數(shù)據(jù)的字符串,你可以預(yù)期出現(xiàn)以下的行為:>>> a = ZoneInfo("Europe/Berlin") >>> b = pickle.loads(europe_berlin_pkl) >>> a is b True
ZoneInfo.no_cache(key)
: 當通過繞過緩存的構(gòu)造器構(gòu)造時,ZoneInfo
對象也會基于鍵序列化,但當反序列化時,反序列化過程會使用繞過緩存的構(gòu)造器。 如果europe_berlin_pkl_nc
是一個包含基于ZoneInfo.no_cache("Europe/Berlin")
構(gòu)造的封存數(shù)據(jù)的字符串,你可以預(yù)期出現(xiàn)以下的行為:>>> a = ZoneInfo("Europe/Berlin") >>> b = pickle.loads(europe_berlin_pkl_nc) >>> a is b False
ZoneInfo.from_file(fobj, /, key=None)
: 當通過文件構(gòu)造時,ZoneInfo
對象會在封存時引發(fā)異常。 如果最終用戶想要封存通過文件構(gòu)造的ZoneInfo
,則推薦他們使用包裝類型或自定義序列化函數(shù):或者基于鍵序列化,或者存儲文件對象的內(nèi)容并將其序列化。
該序列化方法要求所需鍵的時區(qū)數(shù)據(jù)在序列化和反序列化中均可用,類似于在序列化和反序列化環(huán)境中都預(yù)期存在對類和函數(shù)的引用的方式。 這還意味著在具有不同時區(qū)數(shù)據(jù)版本的環(huán)境中當解封被封存的 ZoneInfo
時并不會保證結(jié)果的一致性。
函數(shù)?
- zoneinfo.available_timezones()?
獲取一個包含可用 IANA 時區(qū)的在時區(qū)路徑的任何位置均可用的全部有效鍵的集合。 每次調(diào)用該函數(shù)時都會重新計算。
此函數(shù)僅包括規(guī)范時區(qū)名稱而不包括“特殊”時區(qū)如位于
posix/
和right/
目錄下的時區(qū)或posixrules
時區(qū)。小心
此函數(shù)可能會打開大量的文件,因為確定時區(qū)路徑上某個文件是否為有效時區(qū)的最佳方式是讀取開頭位置的“魔術(shù)字符串”。
備注
這些值并不被設(shè)計用來對外公開給最終用戶;對于面向用戶的元素,應(yīng)用程序應(yīng)當使用 CLDR (Unicode 通用區(qū)域數(shù)據(jù)存儲庫) 之類來獲取更為用戶友好的字符串。 另請參閱
ZoneInfo.key
中的提示性說明。
- zoneinfo.reset_tzpath(to=None)?
設(shè)置或重置模塊的時區(qū)搜索路徑 (
TZPATH
)。 當不帶參數(shù)調(diào)用時,TZPATH
會被設(shè)為默認值。調(diào)用
reset_tzpath
將不會使ZoneInfo
緩存失效,因而在緩存未命中的情況下對主ZoneInfo
構(gòu)造器的調(diào)用將只使用新的TZPATH
。to
形參必須是由字符串或os.PathLike
組成的 sequence 或而不是字符串,它們必須都是絕對路徑。 如果所傳入的不是絕對路徑則將引發(fā)ValueError
。
全局變量?
- zoneinfo.TZPATH?
一個表示時區(qū)搜索路徑的只讀序列 -- 當通過鍵構(gòu)造
ZoneInfo
時,鍵會與TZPATH
中的每個條目進行合并,并使用所找到的第一個文件。TZPATH
可以只包含絕對路徑,絕不包含相對路徑,無論它是如何配置的。zoneinfo.TZPATH
所指向的對象可能隨著對reset_tzpath()
的調(diào)用而改變,因此推薦使用zoneinfo.TZPATH
而不是從zoneinfo
導(dǎo)入TZPATH
或是將zoneinfo.TZPATH
賦值給一個長期變量。有關(guān)配置時區(qū)搜索路徑的更多信息,請參閱 配置數(shù)據(jù)源。
異常與警告?
- exception zoneinfo.ZoneInfoNotFoundError?
當一個
ZoneInfo
對象的構(gòu)造由于在系統(tǒng)中找不到指定的鍵而失敗時引發(fā)。 這是KeyError
的一個子類。
- exception zoneinfo.InvalidTZPathWarning?
當
PYTHONTZPATH
包含將被過濾掉的無效組件,例如一個相對路徑時引發(fā)。