Day 19 日期與時間:你知不知道,我等到花兒也謝了
註:本篇文章同步刊載於iT邦幫忙,為鐵人賽之系列文章。
https://ithelp.ithome.com.tw/articles/10247281
接下來我們要聊到日期與時間的處理相關模組:
datetime跟time。
請想像一下,在人生當中,是不是常常有要算日子和時間的時候?
不論是算退伍還有多少天;
算紀念日520天是什麼時候;
算紀念日1000天是什麼時候;
算紀念日2000天是什麼時候……XD
我們可以利用Python的datetime模組來幫忙計算時間日期與時間差,
這樣子就不會在被問今天是什麼日子的時候答不出來了(吧)!
datetime 當中就有date物件 和time物件 ,
接下來的示範還是屬於datetime模組的範疇,
請大家不要跟後面的time模組 搞混歐!
我們先來看看操作日期的date 物件的用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| >>> from datetime import date
>>> doubleten = date(2020, 10, 10) # 順序是年/月/日
>>> doubleten.year, doubleten.month, doubleten.day
(2020, 10, 10)
# 用isoformat()和str()都可以轉成用"-"連接的字串
>>> doubleten.isoformat(), str(doubleten)
('2020-10-10', '2020-10-10')
>>> today = date.today() # today()會取到今天
>>> str(today) # isoformat格式會補0
'2020-10-01'
# 2020-10-01是星期四,weekday的記法是0(星期一)~6(星期日)
# isoweekday的記法則是1(星期一)~7(星期日)
>>> today.weekday(), today.isoweekday()
(3, 4)
# strftime可用來格式化想要的顯示樣態和目標
>>> doubleten.strftime('%Y--%m--%d, WeekDay: %a')
'2020--10--10, WeekDay: Sat'
|
關於strftime以及後面常見的格式,
大體上會跟一般通用的表示法相同,
例如%Y代表年,%m代表月,%d代表日,%a則代表星期幾的縮寫;
其他還有%H(小時)、%M(分)、%S(秒)等等,
可以參考strftime() 和 strptime() Format Codes。
datetime中的time物件操作方式也很類似:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| >>> from datetime import time
>>> time() # datetime的time.time()預設是從0開始
datetime.time(0, 0)
>>> now = time()
>>> now.isoformat()
'00:00:00'
>>> now = time(0,0,0,38) # 最小單位到微秒(百萬分之一秒,也就是10e-6)
>>> now.microsecond # 取微秒
38
>>> now = time(hour=19, second=50)
>>> str(now)
'19:00:50'
>>> now.strftime('%H-%M') # 同樣可以適用strftime
'19-00'
|
或者,兩者都要的話,
可以直接使用datetime.datetime物件!
1
2
3
4
5
6
7
8
9
10
| >>> from datetime import datetime
>>> datetime.today() # 現在的時間,計到微秒
datetime.datetime(2020, 10, 1, 17, 37, 7, 490703)
>>> datetime.utcnow() # UTC標準時間(所以台灣是+8,看出來了嗎?)
datetime.datetime(2020, 10, 1, 9, 37, 43, 823644)
# str這邊和isoformat就會有點不一樣了,isoformat會用"T"來分隔。
>>> str(datetime.now())
'2020-10-01 17:39:03.953659'
>>> datetime.now().isoformat()
'2020-10-01T17:39:23.671787'
|
讀者可能會問:
「不對阿,說好的算紀念日呢?」
要計算日期差距相關的處理,
我們要用到datetime的另一個物件:
timedelta 。
timedelta的建立很簡單,就是timedelta(時間差)。
下面我們假設小亦向阿啾在今年的情人節2/14告白並成功了 ,
接下來我們先來算一下到現在(10/1)為止 ,
他們已經經過了幾天,到後面的紀念日又還有多久呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| >>> from datetime import date, datetime, time ,timedelta
>>> valentine = date(2020, 2, 14)
>>> today = date.today()
>>> romanticlen = today - valentine # date相減會變成timedelta
# 算一算交往時間吧!
>>> romanticlen
datetime.timedelta(days=230)
# 小亦要記得的幾個紀念日
>>> remember = [100, 200, 520, 1000, 2000]
# 注意timedelta也可以用乘上數字來和定點日期相加減計算,相當有彈性
>>> memorialday = [valentine + timedelta(days=i) for i in remember]
>>> memorialday # 咦?這時間怎麼好像有的已經過了?
[datetime.date(2020, 5, 24), datetime.date(2020, 9, 1), datetime.date(2021, 7, 1
8), datetime.date(2022, 11, 10), datetime.date(2025, 8, 6)]
>>> diff = [i - today for i in memorialday] # 來減看看!
>>> diff # 小亦你很糟糕歐,有兩個紀念日已經過了!阿啾會哭哭呦XD
[datetime.timedelta(days=-130), datetime.timedelta(days=-30), datetime.timedelta
(days=290), datetime.timedelta(days=770), datetime.timedelta(days=1770)]
|
講完了datetime,我們現在來講time 模組。
time模組比較簡單一點點,基本上最常用到的就是time.time()。
time.time()會給出Unix標準時間 ,
也就是以1970年1月1號起算到目前為止帶小數點的總秒數(不用背,不會考XD)。
如果使用localtime()的話,則會換算成現在所在時區的時間。
1
2
3
4
5
6
| >>> import time
>>> time.time()
1601547391.7189288
>>> time.localtime() # 筆者電腦目前是2020年10月1日下午6點16分
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=1, tm_hour=18, tm_min=16, tm_s
ec=34, tm_wday=3, tm_yday=275, tm_isdst=0)
|
上面範例中的struct_time是time的另一個物件,
作用是可以用來給定一個指定的時間方便處理。
我們也可以使用time.ctime()或time.strftime(格式化字串, 時間),
將其轉換成易讀的字串。
1
2
3
4
5
| >>> now = time.localtime()
>>> time.ctime()
'Thu Oct 1 18:22:46 2020'
>>> time.strftime('現在是%A, %Y年%m月%d日的%H時%M分%S秒', now)
'現在是Thursday, 2020年10月01日的18時22分35秒'
|
不同的國家語系,給出來的縮寫等會不同,
如果要再精細轉換的話,可以使用local進行setlocale()的操作,
有興趣的話,可以再進一步研究一下用法。
但最常被簡單用到的方式還是time.time()跟time.sleep()了 !
通常狀況下,我們會在跑完一段想測量的程式以後,
使用time.time()的差值 來計算時間。
time.sleep()則可以讓程式暫時停止執行指定的秒數 ,
待時間到才繼續運作。
我們拿前面的os的程式來修改一下測試這兩個方法,
會發現多次測試下,扣掉10秒以後,(因為10秒是我們睡掉的XD)
耗時其實差距蠻大的。
要取得一個比較良好的數據,
就可能要用迴圏來多測幾次,再取平均值。
1
2
3
4
5
6
7
8
9
10
11
| import os, time
start = time.time()
for path, dirs, files in os.walk('.'):
print(path)
for f in files:
print(os.path.join(path, f))
for d in dirs:
print(os.path.join(path, d))
time.sleep(10) # 睡10秒鐘(可以給小數)
end = time.time()
|
1
| print("總耗時:%f" % (end - start))
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| C:\Users\Desolve\utils>python fromzero.py
.
.\bookstore.json
.\check.py
.\fromzero.py
.\poem.txt
.\schedule.py
.\__init__.py
.\csv
.\json
.\__pycache__
.\csv
.\csv\student.csv
.\csv\student_dic.csv
.\json
.\json\classA.json
.\__pycache__
.\__pycache__\check.cpython-38.pyc
.\__pycache__\schedule.cpython-38.pyc
.\__pycache__\__init__.cpython-38.pyc
總耗時:10.003572
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| C:\Users\Desolve\utils>python fromzero.py
.
.\bookstore.json
.\check.py
.\fromzero.py
.\poem.txt
.\schedule.py
.\__init__.py
.\csv
.\json
.\__pycache__
.\csv
.\csv\student.csv
.\csv\student_dic.csv
.\json
.\json\classA.json
.\__pycache__
.\__pycache__\check.cpython-38.pyc
.\__pycache__\schedule.cpython-38.pyc
.\__pycache__\__init__.cpython-38.pyc
總耗時:10.002572
|
最後我們來做個練習吧!
- 承前面小亦和阿啾的狀況需要補救,
請幫其重新列出接下來到明年(2021)幾個重要的節日的時間,
計算距離2020–10–01的天數,並排序將其從近排到遠 ,
這樣小亦才不會漏掉。(1000天或2000天什麼的先不用算)
[七夕(2021–08–14)、情人節(2021–02–14)、白色情人節(2021–03–14)、阿啾生日(2020–10–03)、阿啾生日(2021–10–03)]
(什麼?你說為什麼有兩個生日?生日當然要每個生日都要過阿,
會問這個問題的讀者請檢討一下自己是不是憑實力單身阿XD?)
那麼,我們就明天見囉!
工商時間:
抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)
在Python Taiwan的連結第100篇的文章 底下,
公開分享到你的臉書、按讚該篇文章、並留言告訴我說,
「你最喜歡這一整個系列的哪一篇?為什麼?」或
「除了從LeetCode學演算法系列以外,
你還想要看到關於什麼方向的文章?」
超過20則留言的話 (有完成以上步驟的才算),我們就抽一組
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
課程的免費兌換券進行贈送!
期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)
容筆者工商一下,
「從Leetcode學演算法|進階篇」 開放預購啦!
這次選了40道難度加深的LeetCode題目,
同樣也會細部解說對應的技巧及須要掌握的演算法!
同時這次購買進階篇的話,
額外還加贈**「從Leetcode學演算法|面試篇」** !
當中包含了面試準備須知分享 ,及訪談國內外不同經驗的工程師 ,
讓你不論是想走前端/後端/一般軟工 或者是想找國外的工作 ,
是初學想轉職 還是正在工作 ,都能夠從中得到收穫呦!
有興趣的朋友可以使用下面的早鳥優惠~
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」 :
https://bit.ly/advleetcode
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠:
https://bit.ly/allleetcode