日期的轉換及計算
對於日期,有時需執行不同時間單位的轉換,或者接受字符串格式的日期,轉換爲 datetime
對象。有時需計算日期的範圍,以及特定某個星期幾的日期。這裏更多用到的是 Python 提供的 datetime
模塊。
datetime 模塊
日期與時間的簡單轉換
datetime
模塊中可以通過創建 timedelta
對象表示一個時間段。如下示例:
>>> 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
對象然後使用標準數學運算執行操作。示例如下:
>>> 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
對象能夠自行處理閏年的問題,如下示例:
>>> 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()
方法實現,如下代碼:
>>> 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 | 補零後十進制表示的秒 |
將日期格式化爲英文易讀形式,如下:
>>> 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
,可用如下代碼實現解析函數:
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 [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
模塊實現需求:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
'''
@File: datetime_calendar.py
@Time: 2020/01/15 12:46:58
@Author: 大夢三千秋
@Contact: [email protected]
'''
# 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)
在交互式解釋器中使用如下:
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
以上就是本篇的主要內容