在 Python 中處理日期和時間有點麻煩。所幸,Python 提供了一種內置的方式來簡化這種操作:Python 的 Datetime 模塊。
datetime 可以幫助我們識別並處理與時間相關的元素,如日期,小時,分鐘,秒,星期,月份,年份等。它提供了諸如時區和夏令時等很多服務。還可以處理時間戳數據,解析星期幾,每月幾號,以及從字符串格式化日期和時間等。
簡而言之,datetime 是 Python 中處理日期和時間的一大利器。我們現在來深入了解一下。
本節教程中,我們將會學習很多 datetime 中很多詳細的方法,包括:
獲取年,月,日,時,分
獲取星期幾與一年中的第幾天
轉換日期對象為 DataFrame 索引
學習本教程時,我們建議你在自己的機器上運行一下這些代碼。
Python 的 datetime 類在編寫代碼之前,有必要先了解一下 datetime 模塊中提供的五個主要的對象類。根據我們具體需要執行的操作,我們可能需要使用其中的一個或多個類。
datatime:允許我們同時操作時間和日期(月,日,年,時,秒,微秒)。
date:允許我們排除時間僅操作日期(月,日,年)
time:允許我們排除日期僅操作時間(時,分,秒,微秒)
timedelta:一個用於操作日期以及測量的時間跨度
tzinfo:一個用於處理時區的抽象類
如果還是不太理解它們之間的區別,也沒關係。我們接下來就深入學習一下 datetime 的工作方式,來更好地理解和使用它們。
創建 Date 對象首先,我們來仔細看看 datetime 對象。由於 datetime 既是模塊名也是模塊內的類名,所以我們要從 datetime模塊內引用 datetime 類。
然後,列印當前日期和時間來查看 datetime 對象中都包含什麼。可以使用 datetime 類的 .now() 函數創建一個 datetime 對象,然後列印這個對象,之後再使用 type() 函數列印這個對象的類型。如此,我們可以看到更詳細的信息。
從上面的結果中,我們可以看到 datetime_object 是 datetime 類的對象實例,對象中包含了年,月,日,時,分,秒,以及毫秒。
從 Date 中提取年份和月份我們現在已經理解了 datetime 對象的構成,那麼我們可以猜一下 date 和 time 對象是怎樣的。因為我們已經知道 date 對象可以理解為 datetime 去掉了時間數據,而 time 對象可以理解為 datetime 去掉了日期數據。
我們還可以解決很多問題。比如,大多數數據集中,日期和時間信息是以字符串格式存儲的。另外,我們可能不希望拿到所有的日期和時間數據,當我們在做一些諸如月度銷售分析的時候,那麼將信息分解到毫秒級別的用處並不大。
現在,我們來聚焦於數據科學中的一項常見任務:使用 datetime 從字符串中提取我們實際想要的元素。
為了實現這個目的,我們還需要做一些其他的工作。
使用 strptime() 和 strftime() 處理日期和時間字符串幸運的是,datetime 提供了兩個方法,strptime() 和 strftime(),可以在字符串與 datetime 對象之間互相轉換。strptime() 可以讀取字符串中的日期與時間信息並將其轉換為 datetime 對象,而 strftime 則是將 datetime 對象轉換為字符串。
當然,strptime() 並沒有魔法,它不能將任意字符串轉換為日期和時間,它需要一些人為地幫助,來解釋它究竟識別到了什麼。但是它只能識別大多數常規的日期和時間字符串格式(詳情請查閱文檔)。我們現在給定一個日期格式字符串 "YYYY-MM-DD",來看看 strptime() 方法能做什麼。
可以看到 strptime() 方法接收兩個參數:字符串 my_string 以及 "%Y-%m-%d",多出來的這個字符串告訴 strptime() 方法如何解釋傳入的字符串 my_string。比如,"%Y" 表示期望從字符串的前四個字符中讀取年份。
這篇文檔中完整地列出了這些可匹配的模式,我們將在教程後面的部分詳細介紹這些方法。
你可能還注意到日期後面還跟著時間信息 00:00:00。這是因為我們創建了一個 datetime 對象,必然會包含日期和時間。如果我們在輸傳入的字符串中沒有指明時間,將會用 00:00:00 作為默認時間。
>>> 今日籤到口令:9nad <<<
先不論其他,我們希望的是從日期中分離出特定的元素用於分析。一個辦法是使用 datetime 對象內置的類屬性,如 .month 或 .year。
我們現在來提取更多的信息,這也確實是一個常見的任務。此時,我們將嘗試從 my_date 對象中獲取月份中某一天以及年份中的某一天。通過 datetime 對象的 .weekday() 函數可以得到一個星期幾的數字,但是我們可以通過使用 calendar 模塊中的 day_name 方法將其轉化為文本格式(如,Monday,Tuesday,Wednesday 等等)。
我們首先會導入 calendar,之後會用到 my_date 對象的 .day 屬性以及 .weekday() 方法。這樣我們就可以獲取到星期幾的文本格式:
先等一下,這裡看起來有一點奇怪。一周的第三天應該是 Wednesday 而不是 Thursday 啊。
我們這裡使用一個循環來仔細看一下 day_name 變量中的信息:
現在我們知道 Python 中星期是從 Monday 開始的,其計數下標則是從 0 開始而不是從 1 開始。所以這就解釋了我們上面看到的為什麼數字 3 轉換成了 "Thursday"。
從 Python 的 Datetime 對象中獲取小時和分鐘我們現在來關注一下時間以及從 datetime 對象中提取小時和分鐘。與上面我們處理月份和年份相似,我們可以使用類屬性 .hour 和 .minute 獲取到一天中小時與分鐘信息。
使用 .now() 函數來設置一個新的日期和時間。當寫到這裡的時候,時間是 2019 年 10 月 25 日上午 10 點 25 分。當然,根據你運行這段代碼的時間,結果可能與之不同。
我們還可以使用 datetime 做很多有趣的事。例如,我們可能想知道現在是一年中的第幾個星期。
使用 datetime 對象的 isocalendar 函數,我們可以獲取到年份,一年中的星期數,和一周中的第幾天。
特別注意,isocalendar 返回的是帶有 ISO 年份,星期數和工作日的元組。這個 ISO 日曆是基于格裡高利歷的一種被廣泛使用的標準日曆。你可以點擊連結了解更多詳細信息。但是出於我們現在的目的,我們只需要知道它是作為一種常規日曆,且每星期是從星期一開始的就可以了。
注意,在 ISO 日曆中,每星期是從 1 開始計數的,所以這裡的 5 真正表示的是星期五:Friday。
從上面我們可以看到當前是今天的第 43 個星期,但是如果你只想獲得這個數字,可以像其他 Python 中的列表或元組一樣,使用下標索引的方式實現:
編程的時候,會經常遇到使用時間戳格式存儲的時間和日期,或者希望以 Unix 時間戳格式存儲你的數據。
我們可以使用 datetime 的內置函數 timestamp(),他可以接收一個 datetime 對象作為參數並返回一個時間戳格式的日期和時間:
與之相似,我們可以使用 fromtimestamp() 執行與上面相反的操作。這是 datetime 類中提供的一個方法,可以接收一個(浮點型格式的)時間戳作為參數,並返回一個 datetime 對象,像下面這樣:
很多時候,我們可能希望使用 Python 中的 datetime 來測量一段時間跨度,或者一段持續的時間。這個可以使用 datetime 內置的 timedelta 類。一個 timedelta 對象可以表示兩個日期或時間的差值。有了這個我們就可以測量時間跨度,或者對日期及時間進行加減操作等。
將所有參數置為 0 即可創建一個默認的 timedelta 對象。現在我們來創建一個時間跨度為兩周的 timedelta 對象:
注意,這裡我們使用 timedelta 類的 .days 屬性來獲取以天為單位的持續時間。參照文檔,我們還可以獲取以秒和毫秒為單位的持續時間。
現在創建另一個 timedelta 持續時間再練習一下:
現在我們結合使用 datetime 對象和 timedelta 對象來做一些數學計算。比如說在當前日期和時間上加上一些不同的時間跨度,來看看十五天後的日期,或者是兩周前是哪天。
為此,我們可以使用運算符 + 或 - 來對 datetime 對象增加或減去 timedelta 對象實現。得到的結果是 datetime 加上或減去 timedelta 對象所代表的的時間跨度後的新時間。是不是很棒?
(注意:在下面的代碼中,時間是 10 月 25 日 11:12。這可能與你實際使用 .now() 函數得到的 datetime 對象有所不同。)
注意,這裡計算後輸出的結果仍然是一個 datetime 對象。
比較兩個日期和時間之間的差值與上面的操作類似,我們還可以使用 datetime 來為一個日期加上或減去另一個日期,來得到一個時間跨度。
由於計算的結果是一個時間片,當我們對一個日期對象減去另一個日期對象得到的就是一個 timedelta 對象。
這裡,我們創建了兩個日期對象(注意,它們與 datetime 對象相比,除了不包含時間信息,其他都是一樣的),並且讓其中一個減去另一個得到一個時間跨度。
上述代碼,我們為了簡單起見僅使用了日期 date,同樣也可以使用 datetime 對象做同樣的操作,以獲得包含小時,分鐘和秒的精確量度:
我們先前已經簡單地了解了 strftime() 和strptime() 對象,現在來仔細看一下這些方法,因為它們對於 Python 中處理數據分析通常比較重要。
我們已經使用過 strptime() 方法,你可以將一個格式化後的日期和時間轉換為一個 datetime 對象,函數格式如下:
注意這裡有兩個參數:
現在來試著轉換一個其他類型的日期字符串。這個網站提供了很多非常有用的參考說明,有助於 strptime() 識別我們輸入的字符串:
現在來做一些更高級的操作,驗證一下目前所學。以一個格式化後的字符串開始,將其轉換為 datetime 對象,並且看看不同的格式化方式(dd/mm 和 mm/dd)得到的結果。
然後,基於 mm/dd 的格式,我們將其轉換為 Unix 時間戳。之後轉回 datetime 對象,再使用幾種不同的 strftime 模式將轉換後的字符串輸出:
這裡有一張圖片,可以保存在你常用的備忘錄中,裡面是常用的 strftime() 和 strptime() 模式:
現在使用上面的模式做一些簡單的實踐:
在 Python 中,如果涉及時區的話,處理日期和實踐就會變得很複雜。幸好,pytz 模塊的存在為我們提供了跨時區轉換的能力,它還可以在使用夏令時的地區處理夏令時。
我們可以通過 localize 函數為 Python 中的 datetime 對象加上一個時區信息。然後可以用 astimezone() 將一個已有時區轉換為另一個指定的時區(這個函數接收一個我們期望轉換的時區作為參數)。
有了這個模塊,我們在處理包含多個不同時區的數據集會變得簡單很多。
處理 pandas 中的 Datetime 對象數據科學家熱衷於 pandas 有很多原因。其中之一是它包含了多種用於處理時間序列數據的功能。拿 datetime 自身來說,pandas 中就有 datetime 和 timedelta 對象分別表示日期和時間以及時間片。
我們將日期,時間和時間片字符串通過以下函數轉換為 pandas 中的 datetime 對象。
可以預見,這些函數都很善長將字符串轉換為 Python 中的 datetime 對象,而且可以自動識別它們的格式,而不需要我們定義 strftime 模式。
來看一個實際的例子:
注意,即使我們在字符串中帶有一些複雜的元素,如 "th" 和 "sep" 而不是指明 "Sep." 或 "September",pandas 也可以正確的解析該字符串並返回格式化後的日期。
我們還可以通過 pandas(以及一些與之相關的 numpy 的功能) 自動創建一段範圍內的 pandas 對象序列。比如下面這樣,我們從上面定義的日期開始,創建了一系列十二個日期。然後又用 pd.date_range() 函數創建了另外一系列日期:
對 pandas 的 DataFrame 中每一列使用 dt 屬性,我們能夠輕易地從日期中獲取年,月,日,時,或分。比如,我們可以使用 df['date'].dt.year 從一個包含完整日期信息的 pandas 數據列中單獨解析出年份。
為了方便理解,我們利用上面已經創建的一個序列快速實現一個 DateFrame:
現在使用 Python 中 datetime(通過 dt) 相關的屬性為日期的每個元素創建一個單獨的列:
Pandas 還可以從 datetime 對象中獲取其他的一些元素,比如說星期幾和一年中的某一天。這些同樣可以用 dt屬性來實現。這裡注意一點,Python 中通常每周從周一開始,而下表是 0 ,所以星期的數字 5 表示周六。
我們還可以在 pandas 中將一個 datetime 的列寫入 DateFrame 的索引中。這對於處理一些數據可視化的任務很有用,matplotlib 可以識別出 DateFrame 的索引列是一個時間序列,然後繪製相應的數據。
為了實現這一點,我們需要重新定義 df.index :
本教程中,我們深入討論了 Python 中的 datetime,並且還學習了 pandas 及其 calendar 模塊的一些知識。我們已經介紹了很多東西,不過要記住:最好的學習方式是親自動手寫代碼。
英文原文:https://www.dataquest.io/blog/python-datetime-tutorial/轉發是最大的鼓勵!謝謝您的支持!
重要通知
想加入工控上位機學習技術交流群
請添加班長為好友
並備註:地區-行業-姓名暱稱獲取進群資格。
分享到朋友圈,和朋友們一起分享吧
——————————————————————
▣ 來源:工控課堂www.gkket.com,侵刪!
▣ 聲明:本文素材系網絡收集,工控上位機學習編輯整理。文中所用視頻、圖片、文字版權歸原作者所有。但因轉載眾多,無法確認真正原始作者,故僅標明轉載來源。如涉及作品版權問題,煩請及時聯繫17621634088(微信同號),我們將即刻確認版權並按國家相關規定支付稿酬!