1. 程式人生 > 程式設計 >Python 日期的轉換及計算的具體使用詳解

Python 日期的轉換及計算的具體使用詳解

日期的轉換及計算

對於日期,有時需執行不同時間單位的轉換,或者接受字串格式的日期,轉換為 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,28)
>>> a - b
datetime.timedelta(2)
>>> (a - b).days
2
>>> c = datetime(2019,1)
>>> d = datetime(2019,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,15,0)
>>> z = datetime.now()
>>> z
datetime.datetime(2020,11,10,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,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,day_s = s.split('-')
  ...:   return datetime(int(year_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 例項進行遞增日期。

參考資料

來源

  1. David M. Beazley;Brian K. Jones.Python Cookbook,3rd Edtioni.O'Reilly Media.2013.
  2. "8.1. datetime — Basic date and time types".docs.python.org.Retrieved 11 January 2020
  3. "8.2. calendar — General calendar-related functions".docs.python.org.Retrieved 13 January 2020

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。