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