Python 的6个日期时间库
曾幾何時(shí),我們中的一個(gè)人(Lacey)盯了一個(gè)多小時(shí)的python文檔中描述日期和時(shí)間格式化字符串的表格。當(dāng)我試圖編寫從 API 中將日期時(shí)間字符串轉(zhuǎn)換為Python datetime對(duì)象時(shí),我很難理解其中的特定部分,因此我決定請(qǐng)求幫助。
有人問(wèn)道:“為什么你不使用 dateutil 呢?”
讀者,如果你沒(méi)有從這個(gè)月的 Python 專欄中獲得任何東西,只是學(xué)習(xí)到有比 datetime 的 strptime 更容易地將 datetime 字符串轉(zhuǎn)換為 datetime 對(duì)象的方法,那么我們覺得就已經(jīng)成功了。
但是,除了將字符串轉(zhuǎn)換為更有用的 Python 對(duì)象之外,還有許多庫(kù)都有一些有用的方法和工具,可以讓您更輕松地進(jìn)行時(shí)間測(cè)試、將時(shí)間轉(zhuǎn)換為不同的時(shí)區(qū)、以人類可讀的格式傳遞時(shí)間信息,等等。如果這是你在 Python 中第一次接觸日期和時(shí)間,請(qǐng)暫停并閱讀如何使Python的日期和時(shí)間 。要理解為什么在編程中處理日期和時(shí)間是困難的,請(qǐng)閱讀 《愚蠢的程序員相信時(shí)間》
隨意跳過(guò)那些你已經(jīng)熟悉的庫(kù),專注于那些對(duì)你而言是新的庫(kù)。
內(nèi)建的 datetime 模塊
在跳轉(zhuǎn)到其他庫(kù)之前,讓我們回顧一下如何使用 datetime 模塊將日期字符串轉(zhuǎn)換為 Python datetime 對(duì)象。
假設(shè)我們從 API 接受到一個(gè)日期字符串,并且需要它作為 Python datetime 對(duì)象存在:
這個(gè)字符串包括:
日期是 YYYY-MM-DD 格式的
字母 T 表示時(shí)間即將到來(lái)
時(shí)間是 HH:II:SS 格式的
表示此時(shí)間的時(shí)區(qū)指示符 Z 采用 UTC (詳細(xì)了解日期時(shí)間字符格式)
要使用 datetime 模塊將此字符串轉(zhuǎn)換為 Python datetime 對(duì)象,你應(yīng)該從 strptime 開始。 datetime.strptime 接受日期字符串和格式化字符并返回一個(gè) Python datetime 對(duì)象。
我們必須手動(dòng)將日期時(shí)間字符串的每個(gè)部分轉(zhuǎn)換為 Python 的 datetime.strptime 可以理解的合適的格式化字符串。四位數(shù)年份由 %Y 表示,兩位數(shù)月份是 %m,兩位數(shù)的日期是 %d。在 24 小時(shí)制中,小時(shí)是 %H,分鐘是 %M,秒是 %S。
為了得出這些結(jié)論,需要在Python 文檔的表格中多加注意。
由于字符串中的 Z 表示此日期時(shí)間字符串采用 UTC,所以我們可以在格式中忽略此項(xiàng)。(現(xiàn)在,我們不會(huì)擔(dān)心時(shí)區(qū)。)
轉(zhuǎn)換的代碼是這樣的:
格式字符串很難閱讀和理解。我必須手動(dòng)計(jì)算原始字符串中的字母 T 和 “Z”的位置,以及標(biāo)點(diǎn)符號(hào)和格式化字符串,如 %S 和 %m。有些不太了解 datetime 的人閱讀我的代碼可能會(huì)發(fā)現(xiàn)它很難理解,盡管其含義已有文檔記載,但它仍然很難閱讀。
讓我們看看其他庫(kù)是如何處理這種轉(zhuǎn)換的。
Dateutil
dateutil 模塊對(duì) datetime 模塊做了一些擴(kuò)展。
繼續(xù)使用上面的解析示例,使用 dateutil 實(shí)現(xiàn)相同的結(jié)果要簡(jiǎn)單得多:
如果字符串包含時(shí)區(qū),那么 dateutil 解析器會(huì)自動(dòng)返回字符串的時(shí)區(qū)。由于我們?cè)?UTC 時(shí)區(qū),你可以看到返回來(lái)一個(gè) datetime 對(duì)象。如果你想解析完全忽略時(shí)區(qū)信息并返回原生的 datetime 對(duì)象,你可以傳遞 ignoretz=True 來(lái)解析,如下所示:
1 4$ from dateutil.parser import parse 2 $ parse('2018-11-29T17:45:25Z', ignoretz=True) 3 datetime.datetime(2018, 11, 29, 17, 45, 25)dateutil 還可以解析其他人類可讀的日期字符串:
1 3$ parse('November 29th, 2018 at 5:45 pm') 2 datetime.datetime(2018, 11, 29, 17, 45)dateutil 還提供了像 relativedelta 的工具,它用于計(jì)算兩個(gè)日期時(shí)間之間的時(shí)間差或向日期時(shí)間添加或刪除時(shí)間,rrule 創(chuàng)建重復(fù)日期時(shí)間,tz 用于解決時(shí)區(qū)以及其他工具。
Arrow
Arrow 是另一個(gè)庫(kù),其目標(biāo)是操作、格式化,以及處理對(duì)人類更友好的日期和時(shí)間。它包含 dateutil,根據(jù)其文檔,它旨在“幫助你使用更少的包導(dǎo)入和更少的代碼來(lái)處理日期和時(shí)間”。
要返回我們的解析示例,下面介紹如何使用 Arrow 將日期字符串轉(zhuǎn)換為 Arrow 的 datetime 類的實(shí)例:
你也可以在 get() 的第二個(gè)參數(shù)中指定格式,就像使用 strptime 一樣,但是 Arrow 會(huì)盡力解析你給出的字符串,get() 返回 Arrow 的 datetime 類的一個(gè)實(shí)例。要使用 Arrow 來(lái)獲取 Python datetime 對(duì)象,按照如下所示鏈?zhǔn)?datetime:
1 3$ arrow.get('2018-11-29T17:45:25Z').datetime 2 datetime.datetime(2018, 11, 29, 17, 45, 25, tzinfo=tzutc())通過(guò) Arrow datetime 類的實(shí)例,你可以訪問(wèn) Arrow 的其他有用方法。例如,它的 humanize() 方法將日期時(shí)間翻譯成人類可讀的短語(yǔ),就像這樣:
1 5$ import arrow 2 $ utc = arrow.utcnow() 3 $ utc.humanize() 4 'seconds ago'在 Arrow 的文檔中關(guān)于其有用方法的信息。
Moment
Moment 的作者認(rèn)為它是“內(nèi)部測(cè)試版”,但即使它處于早期階段,它也是非常受歡迎的,我們想來(lái)討論它。
Moment 的方法將字符轉(zhuǎn)換為其他更有用的東西很簡(jiǎn)單,類似于我們之前提到的庫(kù):
就像其他庫(kù)一樣,它最初返回它自己的 datetime 類的實(shí)例,要返回 Python datetime 對(duì)象,添加額外的 date() 調(diào)用即可。
1 3$ moment.date('2018-11-29T17:45:25Z').date 2 datetime.datetime(2018, 11, 29, 17, 45, 25, tzinfo=<StaticTzInfo 'Z'>)這將 Moment datetime 類轉(zhuǎn)換為 Python datetime 對(duì)象。
Moment 還提供了使用人類可讀的語(yǔ)言創(chuàng)建新日期的方法。例如創(chuàng)建一個(gè)明天的日期:
它的 add() 和 subtract() 命令使用關(guān)鍵字參數(shù)來(lái)簡(jiǎn)化日期的操作。為了獲得后天,Moment 會(huì)使用下面的代碼:
1 3$ moment.date("tomorrow").add(days=1) 2 <Moment(2018-11-07T11:26:48)>Maya
Maya 包含了 Python 中其他流行處理日期時(shí)間的庫(kù),包括 Humanize、 pytz 和 pendulum 等等。這個(gè)項(xiàng)目旨在讓人們更容易處理日期。
Maya 的 README 包含幾個(gè)有用的實(shí)例。以下是如何使用 Maya 來(lái)重新處理以前的解析示例:
注意我們必須在 maya.parse() 之后調(diào)用 datetime()。如果我們跳過(guò)這一步,Maya 將會(huì)返回一個(gè) MayaDT 類的示例:。
由于 Maya 與 datetime 庫(kù)中很多有用的方法重疊,因此它可以使用 MayaDT 類的實(shí)例執(zhí)行諸如使用 slang_time() 方法將時(shí)間偏移量轉(zhuǎn)換為純文本語(yǔ)言,并將日期時(shí)間間隔保存在單個(gè)類的實(shí)例中。以下是如何使用 Maya 將日期時(shí)間表示為人類可讀的短語(yǔ):
顯然,slang_time() 的輸出將根據(jù)距離 datetime 對(duì)象相對(duì)較近或較遠(yuǎn)的距離而變化。
Delorean
Delorean,以 《返回未來(lái)》 電影中的時(shí)間旅行汽車命名,它對(duì)于操縱日期時(shí)間特別有用,包括將日期時(shí)間轉(zhuǎn)換為其他時(shí)區(qū)并添加或減去時(shí)間。
Delorean 需要有效的 Python datetime 對(duì)象才能工作,所以如果你需要使用時(shí)間字符串,最好將其與上述庫(kù)中的一個(gè)配合使用。例如,將 Maya 與 Delorean 一起使用:
現(xiàn)在,你有了一個(gè) datetime 對(duì)象 d_t,你可以使用 Delorean 來(lái)做一些事情,例如將日期時(shí)間轉(zhuǎn)換為美國(guó)東部時(shí)區(qū):
1 7$ from delorean import Delorean 2 $ d = Delorean(d_t) 3 $ d 4 Delorean(datetime=datetime.datetime(2018, 11, 29, 17, 45, 25), timezone='UTC') 5 $ d.shift('US/Eastern') 6 Delorean(datetime=datetime.datetime(2018, 11, 29, 13, 45, 25), timezone='US/Eastern')看到小時(shí)是怎樣從 17 變成 13 了嗎?
你也可以使用自然語(yǔ)言方法來(lái)操作 datetime 對(duì)象。獲取 2018 年 4 月 29 日之后的下個(gè)星期五(我們現(xiàn)在使用的):
在 Delorean 的文檔中關(guān)于其的用法。
Freezegun
Freezegun 是一個(gè)可以幫助你在 Python 代碼中測(cè)試特定日期的庫(kù)。使用 @freeze_time 裝飾器,你可以為測(cè)試用例設(shè)置特定的日期和時(shí)間,并且所有對(duì) datetime.datetime.now()、 datetime.datetime.utcnow() 等的調(diào)用都將返回你指定的日期和時(shí)間。例如:
要跨時(shí)區(qū)進(jìn)行測(cè)試,你可以將 tz_offset 參數(shù)傳遞給裝飾器。freeze_time 裝飾器也接受更簡(jiǎn)單的口語(yǔ)化日期,例如
@freeze_time(‘April 4, 2017’)。
上面提到的每個(gè)庫(kù)都提供了一組不同的特性和功能,也許很難決定哪一個(gè)最適合你的需要。Maya 的作者, Kenneth Reitz 說(shuō)到:“所有這些項(xiàng)目相輔相成,它們都是我們的朋友”。
這些庫(kù)共享一些功能,但不是全部。有些擅長(zhǎng)時(shí)間操作,有些擅長(zhǎng)解析,但它們都有共同的目標(biāo),即讓你對(duì)日期和時(shí)間的工作更輕松。下次你發(fā)現(xiàn)自己對(duì) Python 的內(nèi)置 datetime 模塊感到沮喪,我們希望你可以選擇其中的一個(gè)庫(kù)進(jìn)行試驗(yàn)。
總結(jié)
以上是生活随笔為你收集整理的Python 的6个日期时间库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python 程序员最常犯的十个错误,作
- 下一篇: 25个python相关的基础概念总结