1. 寫在前面
關於時間相關的處理無處不在, 比如日誌管理必然要記錄時間, 統計程序執行開始、結束時間, 測試函數的執行時長, 在時間序列的相關分析上, 也往往用到python的時間模塊和pandas的時間處理相結合, 所以瞭解python時間模塊的一些常用操作也是非常重要的, 這篇文章就小總一下python的時間模塊的使用方法, 同樣, 以後再遇到時間模塊的內容, 會繼續補充, 也同樣, 依然是從使用的角度出發。
python與時間處理相關的模塊有兩個: time模塊和datetime模塊。
- time模塊提供兩種時間表達方式(假定一個零點基準,偏移長度換算爲按秒的數值型和由 9 個整數組成的元組 struct_time 表示的時間), 前面這種一般在測試函數的執行時長時候用到, 後者比較常用。
- datetime模塊, 常用類4個(date, time, datetime, timedelta), 後面會一一看看常用的操作
最後再整理一個calendar, 這裏面也是提供了一些挺有意思的功能。
Ok, let’s go!
2. time模塊
使用之前, 要導入時間模塊
import time
time模塊提供了時間相關的類和函數。 常用的就是一個類struct_time, 這裏面有表示時間的9個整數組成的元組。 關於time模塊, 常用的是下面的5個函數:
# 當前時間浮點數 time()
second = time.time() # 1592451544.5129032
這個一般在測試函數執行速度的時候用到, 在函數執行前用start統計當前時間, 函數執行完畢用end統計當前時間, 然後兩者一減就可以看出該函數的執行速度。
# 時間數組 localtime() 這個函數就可以把上面的這種浮點轉成struct_time
local_time = time.localtime(second)
local_time # 這裏面就可以獲取相應的屬性, tm_wday表示周幾, tm_yday表示一年的第多少天
## 結果:
time.struct_time(tm_year=2020, tm_mon=6, tm_mday=18, tm_hour=10, tm_min=21, tm_sec=56, tm_wday=3, tm_yday=170, tm_isdst=0)
通過相應的屬性名就可以獲取相應的時間值, 但是這個看起來依然不是我們想要的時間格式, 那麼我們就可以用下面的兩個函數獲取我們看的比較順眼的時間格式:
# 時間字符串 time 類 asctime 方法,轉換 struct_time 爲時間字符串
str_time = time.asctime(local_time)
str_time # 'Thu Jun 18 10:21:56 2020'
# 如果上面的還不順眼, 可以自己格式化時間
# 格式化字符串 time 類 strftime 方法,按照時間格式要求,格式化 struct_time 爲時間字符串
format_time = time.strftime('%Y-%m-%d %H:%M:%S', local_time)
format_time # '2020-06-18 10:21:56'
這樣是不是好看多了。下面再介紹一個,就是把這種格式再變回到struct_time的那種格式:
# 字符時間轉時間數組 strptime()
str_to_struct = time.strptime(format_time, '%Y-%m-%d %H:%M:%S') # 注意:第二個參數的時間格式,要匹配上第一個參數的時間格式。
str_to_struct
## 結果:
time.struct_time(tm_year=2020, tm_mon=6, tm_mday=18, tm_hour=10, tm_min=21, tm_sec=56, tm_wday=3, tm_yday=170, tm_isdst=-1)
最後還要記住常用的時間格式:
- %Y :年
- %m :月 取值 [01,12]
- %d :天 取值 [01,31]
- %H :小時 取值 [00,23]
- %M :分鐘 取值 [00,59]
- %S :秒 取值 [00,61] 閏秒
關於時間模塊, 比較常用的就這5個函數了。
3. datetime模塊
datetime模塊裏面有四個常用類, date, datetime, time, timedelta。
- date: 日期類, 包括屬性年月日及相關方法
- time: 時間類, 包括屬性時分秒及相關方法
- datetime: 日期時間,繼承於 date,包括屬性年、月、日、時、分、秒等及相關方法,其中年月日必須參數
- timedelta: 兩個 datetime 值的差,比如相差幾天(days)、幾小時(hours)、幾分(minutes)等
看起來挺複雜, 但是從使用的角度來看, 用到的東西也不是太多, 下面一一來看, 首先依然是先導入:
from datetime import date, time, datetime, timedelta
-
date
: date表示日期, 能用的無非是打印當前日期, 當前日期轉成格式字符串, 然後再變回去, 方法和上面time模塊裏面的差不多。# 打印當前日期 tod = date.today() tod # datetime.date(2020, 6, 18) # 當前日期字符串 str_date = date.strftime(tod, '%Y-%m-%d') str_date # '2020-06-18' # 字符日期轉日期 # date 類裏沒有 strptime 方法,它的子類 datetime 纔有解析字符串日期的方法 strptime。 str_to_date = datetime.strptime('2020-02-22', '%Y-%m-%d') str_to_date # datetime.datetime(2020, 2, 22, 0, 0)
-
datetime
: 這個類繼承於date, 並且在日期的基礎上加上了time。 常用的依然是獲取當前時間, 當前時間格式化, 然後再變回去。# 打印當前時間 right = datetime.now() right # datetime.datetime(2020, 6, 18, 10, 31, 43, 759828) # 當前時間轉字符串顯示 str_time = datetime.strftime(right, '%Y-%m-%d %H:%M:%S') str_time # '2020-06-18 10:31:43' # 當前時間轉字符串顯示 str_time = datetime.strftime(right, '%Y-%m-%d %H:%M:%S') str_time # datetime.datetime(2020, 6, 18, 10, 31, 43)
-
timedelta
: 求兩個 datetime 類型值的差,返回差幾天:days,差幾小時:hours 等. 相減的兩個時間,不能一個爲 date 類型,一個爲 datetime 類型,儘管兩個類型是父子關係。d1 = datetime.today() d2 = d1 - timedelta(hours=10) print(d1, d2) # 2020-06-18 11:08:26.659060 2020-06-18 01:08:26.659060
這個在時間序列的數據處理上也是非常常用的, 和pandas的
pd.DateOffset
類似, 可以計算時間差, 尤其是做滯後特徵的時候。
4. Calendar模塊
這個模塊也有一些有意思的小案例,比如打印個日曆, 判斷是否閏年, 判斷一個月有幾天, 獲取到月的第一天和最後一天。 下面一一來看:
-
繪製某一年的日曆圖
import calendar year_calerdar_str = calendar.calendar(2020) print(year_calerdar_str)
可以看一下效果:
-
繪製某一個月的日曆圖
# 月的日曆圖 month_calendar_str = calendar.month(2020, 6) print(month_calendar_str)
這樣會單獨打印某個月的日曆圖。
-
判斷某一年是否閏年(之前都是寫代碼判斷的, 什麼能被4整除或者不能被4整除但是能被400整除啥的, 現在竟然有包可調)
# 判斷是否閏年 is_leap = calendar.isleap(2020) is_leap # True
-
判斷一個月有幾天
# 判斷月有幾天 mydate = date.today() weekday, days = calendar.monthrange(mydate.year, mydate.month) print(weekday, days) # weekday表示該月的第一天是周幾, days表示該月有多少天 # 結果: 0 30
-
月的第一天和最後一天
# 月的第一天和最後一天 mydate = date.today() # 第一天 month_first_day = date(mydate.year, mydate.month, 1) # 最後一天 _, days = calendar.monthrange(mydate.year, mydate.month) month_last_day = date(mydate.year, mydate.month, days) print(month_first_day, month_last_day)
好了, 關於python時間模塊常用的一些操作先整理到這裏, 最後給出一個案例,這個案例可以幫忙算算從現在開始還有幾天是女朋友的生日, 這樣每天算一遍, 就不會忘了, 哈哈。
import re
# 計算女朋友的生日離現在還有幾天
def get_days(birthday:str)->int:
splits = re.split(r'[-.\s+/]', birthday)
splits = [s for s in splits if s]
if len(splits) < 3:
raise ValueError('輸入格式不正確, 至少包括年月日')
splits = splits[:3] # 只截取年月日
birthday = datetime.strptime('-'.join(splits), '%Y-%m-%d')
tod = date.today()
delta = birthday.date() - tod
return delta.days
get_days('2020-09-24') # 98