在 Python 中有許多庫可以很容易地測試、轉換和讀取日期和時間資訊。
這篇文章是與 Jeff Triplett 一起合寫的。
曾幾何時,我們中的一個人(Lacey)盯了一個多小時的 Python 文件中描述日期和時間格式化字串的表格。當我試圖編寫從 API 中將日期時間字串轉換為 Python datetime 物件時,我很難理解其中的特定部分,因此我決定請求幫助。
有人問道:“為什麼你不使用 dateutil
呢?”
讀者,如果你沒有從這個月的 Python 專欄中獲得任何東西,只是學習到有比 datetime 的 strptime
更容易地將 datetime 字串轉換為 datetime 物件的方法,那麼我們覺得就已經成功了。
但是,除了將字串轉換為更有用的 Python 物件之外,還有許多庫都有一些有用的方法和工具,可以讓您更輕鬆地進行時間測試、將時間轉換為不同的時區、以人類可讀的格式傳遞時間資訊,等等。如果這是你在 Python 中第一次接觸日期和時間,請暫停並閱讀 如何使用 Python的日期和時間 。要理解為什麼在程式設計中處理日期和時間是困難的,請閱讀 愚蠢的程式設計師相信時間。
這篇文章將會向你介紹以下庫:
- Dateutil
- Arrow
- Moment
- Maya
- Delorean
- Freezegun
隨意跳過那些你已經熟悉的庫,專注於那些對你而言是新的庫。
內建的 datetime 模組
在跳轉到其他庫之前,讓我們回顧一下如何使用 datetime
模組將日期字串轉換為 Python datetime 物件。
假設我們從 API 接受到一個日期字串,並且需要它作為 Python datetime 物件存在:
2018-04-29T17:45:25Z
這個字串包括:
- 日期是
YYYY-MM-DD
格式的 - 字母
T
表示時間即將到來 - 時間是
HH:II:SS
格式的 - 表示此時間的時區指示符
Z
採用 UTC (詳細瞭解日期時間字元格式)
要使用 datetime
模組將此字串轉換為 Python datetime 物件,你應該從 strptime
開始。 datetime.strptime
接受日期字串和格式化字元並返回一個 Python datetime 物件。
我們必須手動將日期時間字串的每個部分轉換為 Python 的 datetime.strptime
可以理解的合適的格式化字串。四位數年份由 %Y
表示,兩位數月份是 %m
,兩位數的日期是 %d
。在 24 小時制中,小時是 %H
,分鐘是 %M
,秒是 %S
。
為了得出這些結論,需要在Python 文件的表格中多加註意。
由於字串中的 Z
表示此日期時間字串採用 UTC,所以我們可以在格式中忽略此項。(現在,我們不會擔心時區。)
轉換的程式碼是這樣的:
$ from datetime import datetime
$ datetime.strptime('2018-04-29T17:45:25Z', '%Y-%m-%dT%H:%M:%SZ')
datetime.datetime(2018, 4, 29, 17, 45, 25)
格式字串很難閱讀和理解。我必須手動計算原始字串中的字母 T
和 “Z”的位置,以及標點符號和格式化字串,如 %S
和 %m
。有些不太瞭解 datetime 的人閱讀我的程式碼可能會發現它很難理解,儘管其含義已有文件記載,但它仍然很難閱讀。
讓我們看看其他庫是如何處理這種轉換的。
Dateutil
dateutil 模組對 datetime
模組做了一些擴充套件。
繼續使用上面的解析示例,使用 dateutil
實現相同的結果要簡單得多:
$ from dateutil.parser import parse
$ parse('2018-04-29T17:45:25Z')
datetime.datetime(2018, 4, 29, 17, 45, 25, tzinfo=tzutc())
如果字串包含時區,那麼 dateutil
解析器會自動返回字串的時區。由於我們在 UTC 時區,你可以看到返回來一個 datetime 物件。如果你想解析完全忽略時區資訊並返回原生的 datetime 物件,你可以傳遞 ignoretz=True
來解析,如下所示:
$ from dateutil.parser import parse
$ parse('2018-04-29T17:45:25Z', ignoretz=True)
datetime.datetime(2018, 4, 29, 17, 45, 25)
dateutil
還可以解析其他人類可讀的日期字串:
$ parse('April 29th, 2018 at 5:45 pm')
datetime.datetime(2018, 4, 29, 17, 45)
dateutil
還提供了像 relativedelta 的工具,它用於計算兩個日期時間之間的時間差或向日期時間新增或刪除時間,rrule 建立重複日期時間,tz 用於解決時區以及其他工具。
Arrow
Arrow 是另一個庫,其目標是操作、格式化,以及處理對人類更友好的日期和時間。它包含 dateutil
,根據其文件,它旨在“幫助你使用更少的包匯入和更少的程式碼來處理日期和時間”。
要返回我們的解析示例,下面介紹如何使用 Arrow 將日期字串轉換為 Arrow 的 datetime 類的例項:
$ import arrow
$ arrow.get('2018-04-29T17:45:25Z')
<Arrow [2018-04-29T17:45:25+00:00]>
你也可以在 get()
的第二個引數中指定格式,就像使用 strptime
一樣,但是 Arrow 會盡力解析你給出的字串,get()
返回 Arrow 的 datetime
類的一個例項。要使用 Arrow 來獲取 Python datetime 物件,按照如下所示鏈式 datetime:
$ arrow.get('2018-04-29T17:45:25Z').datetime
datetime.datetime(2018, 4, 29, 17, 45, 25, tzinfo=tzutc())
透過 Arrow datetime 類的例項,你可以訪問 Arrow 的其他有用方法。例如,它的 humanize()
方法將日期時間翻譯成人類可讀的短語,就像這樣:
$ import arrow
$ utc = arrow.utcnow()
$ utc.humanize()
'seconds ago'
在 Arrow 的文件中閱讀更多關於其有用方法的資訊。
Moment
Moment 的作者認為它是“內部測試版”,但即使它處於早期階段,它也是非常受歡迎的,我們想來討論它。
Moment 的方法將字元轉換為其他更有用的東西很簡單,類似於我們之前提到的庫:
$ import moment
$ moment.date('2018-04-29T17:45:25Z')
<Moment(2018-04-29T17:45:25)>
就像其他庫一樣,它最初返回它自己的 datetime 類的例項,要返回 Python datetime 物件,新增額外的 date()
呼叫即可。
$ moment.date('2018-04-29T17:45:25Z').date
datetime.datetime(2018, 4, 29, 17, 45, 25, tzinfo=<StaticTzInfo 'Z'>)
這將 Moment datetime 類轉換為 Python datetime 物件。
Moment 還提供了使用人類可讀的語言建立新日期的方法。例如建立一個明天的日期:
$ moment.date("tomorrow")
<Moment(2018-04-06T11:24:42)>
它的 add()
和 subtract()
命令使用關鍵字引數來簡化日期的操作。為了獲得後天,Moment 會使用下面的程式碼:
$ moment.date("tomorrow").add(days=1)
<Moment(2018-04-07T11:26:48)>
Maya
Maya 包含了 Python 中其他流行處理日期時間的庫,包括 Humanize、 pytz 和 pendulum 等等。這個專案旨在讓人們更容易處理日期。
Maya 的 README 包含幾個有用的例項。以下是如何使用 Maya 來重新處理以前的解析示例:
$ import maya
$ maya.parse('2018-04-29T17:45:25Z').datetime()
datetime.datetime(2018, 4, 29, 17, 45, 25, tzinfo=<UTC>)
注意我們必須在 maya.parse()
之後呼叫 datetime()
。如果我們跳過這一步,Maya 將會返回一個 MayaDT 類的示例:<MayaDT epoch=1525023925.0>
。
由於 Maya 與 datetime 庫中很多有用的方法重疊,因此它可以使用 MayaDT 類的例項執行諸如使用 slang_time()
方法將時間偏移量轉換為純文字語言,並將日期時間間隔儲存在單個類的例項中。以下是如何使用 Maya 將日期時間表示為人類可讀的短語:
$ import maya
$ maya.parse('2018-04-29T17:45:25Z').slang_time()
'23 days from now
顯然,slang_time()
的輸出將根據距離 datetime 物件相對較近或較遠的距離而變化。
Delorean
Delorean,以 《返回未來》 電影中的時間旅行汽車命名,它對於操縱日期時間特別有用,包括將日期時間轉換為其他時區並新增或減去時間。
Delorean 需要有效的 Python datetime 物件才能工作,所以如果你需要使用時間字串,最好將其與上述庫中的一個配合使用。例如,將 Maya 與 Delorean 一起使用:
$ import maya
$ d_t = maya.parse('2018-04-29T17:45:25Z').datetime()
現在,你有了一個 datetime 物件 d_t,你可以使用 Delorean 來做一些事情,例如將日期時間轉換為美國東部時區:
$ from delorean import Delorean
$ d = Delorean(d_t)
$ d
Delorean(datetime=datetime.datetime(2018, 4, 29, 17, 45, 25), timezone='UTC')
$ d.shift('US/Eastern')
Delorean(datetime=datetime.datetime(2018, 4, 29, 13, 45, 25), timezone='US/Eastern')
看到小時是怎樣從 17 變成 13 了嗎?
你也可以使用自然語言方法來操作 datetime 物件。獲取 2018 年 4 月 29 日之後的下個星期五(我們現在使用的):
$ d.next_friday()
Delorean(datetime=datetime.datetime(2018, 5, 4, 13, 45, 25), timezone='US/Eastern')
在 Delorean 的文件中閱讀更多關於其的用法。
Freezegun
Freezegun 是一個可以幫助你在 Python 程式碼中測試特定日期的庫。使用 @freeze_time
裝飾器,你可以為測試用例設定特定的日期和時間,並且所有對 datetime.datetime.now()
、 datetime.datetime.utcnow()
等的呼叫都將返回你指定的日期和時間。例如:
from freezegun import freeze_time
import datetime
@freeze_time("2017-04-14")
def test():
assert datetime.datetime.now() == datetime.datetime(2017, 4, 14)
要跨時區進行測試,你可以將 tz_offset
引數傳遞給裝飾器。freeze_time
裝飾器也接受更簡單的口語化日期,例如 @freeze_time('April 4, 2017')
。
上面提到的每個庫都提供了一組不同的特性和功能,也許很難決定哪一個最適合你的需要。Maya 的作者, Kenneth Reitz 說到:“所有這些專案相輔相成,它們都是我們的朋友”。
這些庫共享一些功能,但不是全部。有些擅長時間操作,有些擅長解析,但它們都有共同的目標,即讓你對日期和時間的工作更輕鬆。下次你發現自己對 Python 的內建 datetime 模組感到沮喪,我們希望你可以選擇其中的一個庫進行試驗。
via: https://opensource.com/article/18/4/python-datetime-libraries
作者: Lacey Williams Hensche 選題: lujun9972 譯者: MjSeven 校對: wxy
本文由 LCTT 原創編譯,Linux中國 榮譽推出