日期的轉換及計算
對于日期,有時需執行不同時間單位的轉換,或者接受字符串格式的日期,轉換為 datetime 對象。有時需計算日期的范圍,以及特定某個星期幾的日期。這里更多用到的是 Python 提供的 datetime 模塊。
datetime 模塊
日期與時間的簡單轉換
datetime 模塊中可以通過創建 timedelta 對象表示一個時間段。如下示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
>>> from datetime import timedelta >>> a = timedelta(days = 2 , hours = 6 ) >>> b = timedelta(hours = 4.5 ) >>> c = a + b >>> c datetime.timedelta( 2 , 37800 ) >>> c.days 2 >>> c.seconds 37800 >>> c.seconds / 3600 10.5 >>> c.total_seconds() / 3600 58.5 |
如果想表示指定的日期和時間,需要先創建 datetime 對象然后使用標準數學運算執行操作。示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
>>> from datetime import datetime >>> a = datetime( 2020 , 1 , 15 ) >>> print (a + timedelta(days = 10 )) 2020 - 01 - 25 00 : 00 : 00 >>> b = datetime( 2020 , 2 , 3 ) >>> d = b - a >>> d datetime.timedelta( 19 ) >>> d.days 19 >>> now = datetime.today() >>> print (now) 2020 - 01 - 15 10 : 59 : 10.230995 >>> print (now + timedelta(minutes = 10 )) 2020 - 01 - 15 11 : 09 : 10.230995 |
datetime 對象能夠自行處理閏年的問題,如下示例:
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> a = datetime( 2020 , 3 , 1 ) >>> b = datetime( 2020 , 2 , 28 ) >>> a - b datetime.timedelta( 2 ) >>> (a - b).days 2 >>> c = datetime( 2019 , 3 , 1 ) >>> d = datetime( 2019 , 2 , 28 ) >>> c - d datetime.timedelta( 1 ) >>> (c - d).days 1 |
字符串與日期的轉換
當編寫的程序接受以字符串格式表達的日期輸入時,需求為將此類字符串轉換為 datetime 對象進行計算。
使用 datetime 對象中的 strptime() 方法實現,如下代碼:
1
2
3
4
5
6
7
8
9
10
11
|
>>> from datetime import datetime >>> text = '2020-01-15' >>> y = datetime.strptime(text, '%Y-%m-%d' ) >>> y datetime.datetime( 2020 , 1 , 15 , 0 , 0 ) >>> z = datetime.now() >>> z datetime.datetime( 2020 , 1 , 15 , 11 , 10 , 11 , 71792 ) >>> diff = z - y >>> diff datetime.timedelta( 0 , 40211 , 71792 ) |
上述 %Y 的含義是以十進制表示的帶世紀的年份,%m 為以補零后的十進制表示的月份,%d 為以補零后的十進制表示月份中的一天。
以下是幾項格式代碼。例如:
指令 |
含義 |
---|---|
%a |
當地工作日的縮寫 |
% A |
當地工作日的全名 |
% b |
當地月份的縮寫 |
% B |
當地月份的全名 |
% H |
補零后十進制表示的小時(24小時制) |
% I |
補零后十進制表示的小時(12小時制) |
% M |
補零后十進制表示的分鐘 |
% S |
補零后十進制表示的秒 |
將日期格式化為英文易讀形式,如下:
1
2
3
4
5
|
>>> z datetime.datetime( 2020 , 1 , 15 , 11 , 10 , 11 , 71792 ) >>> format_z = datetime.strftime(z, "%A %B %d, %Y" ) >>> format_z 'Wednesday January 15, 2020' |
datetime.strftime() 函數返回一個由顯示格式字符串所指定的代表日期的字符串。格式指令,如上述代碼中的 "%A %B %d, %Y"。其中該函數的第一個參數為 datetime 對象。
這里需要注意的地方是,strptime 的性能比較差。若明確需求是解析大量并且已經知道格式的日期字符串,可以考慮自己實現一套解析方案。假設格式如 YYYY-MM-DD,可用如下代碼實現解析函數:
1
2
3
4
|
from datetime import datetime def parse_ymd(s): year_s, mon_s, day_s = s.split( '-' ) return datetime( int (year_s), int (mon_s), int (day_s)) |
兩者實現的效果:
1
2
3
4
5
6
7
8
9
10
11
12
|
In [ 1 ]: from datetime import datetime ...: def parse_ymd(s): ...: year_s, mon_s, day_s = s.split( '-' ) ...: return datetime( int (year_s), int (mon_s), int (day_s)) In [ 2 ]: text = "2020-01-15" In [ 3 ]: % timeit datetime.strptime(text, '%Y-%m-%d' ) 7.75 µs ± 31 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) In [ 4 ]: % timeit parse_ymd(text) 1.05 µs ± 3.07 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) |
可以看出,parse_ymd() 函數比 datetime.strptime() 快 7 倍多。若是進行大量處理的設計日期,且格式固定的情況下,可以考慮這個方案。
計算某個月份的日期范圍
Python 提供的 calendar 模塊提供了與日歷相關的函數。可以考慮配合 datetime 模塊實現需求:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#!/usr/bin/env python # -*- coding:utf-8 -*- ''' @File: datetime_calendar.py @Time: 2020/01/15 12:46:58 @Author: 大夢三千秋 @Contact: yiluolion@126.com ''' # put the import lib here from datetime import date, timedelta import calendar def get_month_range(start_date = None ): '''獲取月份的范圍 Args: start_date: 開始的日期,默認為 None Returns: 返回包含月份開始日期和結束日期的元組 ''' if start_date is None : # 若 start_date 為空,賦值為當月的第一天 start_date = date.today().replace(day = 1 ) # 獲取月份的天數 _, days_in_month = calendar.monthrange(start_date.year, start_date.month) # 計算結束日期 end_date = start_date + timedelta(days = days_in_month) # 返回開始日期和結束日期的元組 return (start_date, end_date) |
在交互式解釋器中使用如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
In [ 1 ]: from datetime import timedelta In [ 2 ]: from datetime_calendar import get_month_range In [ 3 ]: a_day = timedelta(days = 1 ) In [ 4 ]: first_day, last_day = get_month_range() In [ 5 ]: while first_day < last_day: ...: print (first_day) ...: first_day + = a_day ...: 2020 - 01 - 01 2020 - 01 - 02 2020 - 01 - 03 2020 - 01 - 04 2020 - 01 - 05 2020 - 01 - 06 2020 - 01 - 07 2020 - 01 - 08 ... |
注意:若在交互解釋器下無法導入自己寫的模塊中的方法,嘗試直接在文件所在的路徑下打開交互解釋器。
上面的代碼中,首先將 start_date 對應月份的第一天的日期計算出來。這里使用了 date 對象的 replace() 方法將 day 屬性設置為 1,即表示第一天。
calendar.monthrange() 函數返回指定年份指定月份第一天是星期幾,以及這個月的天數。
獲得月份天數后,加上開始日期可得結束日期。這里需要注意的是,結束日期并不包含在這個日期范圍。在遍歷的時候,判斷條件為 first_day < last_day,不輸出 last_day 的值,以 timedelta 實例進行遞增日期。
參考資料
來源
-
David M. Beazley;Brian K. Jones.Python Cookbook, 3rd Edtioni.O'Reilly Media.2013.
-
"8.1. datetime — Basic date and time types".docs.python.org.Retrieved 11 January 2020
-
"8.2. calendar — General calendar-related functions".docs.python.org.Retrieved 13 January 2020
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://segmentfault.com/a/1190000021592489