2024年8月15日 星期四

Python 學習筆記 : 內建模組 datetime 用法

Python 有兩個時間相關的內建模組 : time 與 datetime, 其中 time 模組主要是以 UNIX 時間戳來處理低階的時間資訊, 但其解析度較低只到秒而已, 無法支援證交所交易資訊精確度高達微秒之要求, 這就是 datetime 模組派上用場的時候了 (datetime 的時間解析度為微秒). 此外,  datetime 模組經常與 Pandas 套件搭配用來處理時間序列資料. 關於 time 模組用法參考 :


參考書籍 :

# Python 自動化的樂趣 (碁峰, H&C) 第 15 章
# 零基礎入門的 Python 自動化投資 (采實, 量化通) 第 4 章
# 一本精通 Python 範例應用大全 (深智, 張宗彥) 第 9-4 節
# Python 股票演算法交易-145 個關鍵技巧詳解 (博碩, 酆世昌 & 劉承彥) 技巧 14

首先用 dir() 檢視 datetime 模組的內容 :

>>> import datetime   
>>> dir(datetime)   
['MAXYEAR', 'MINYEAR', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'date', 'datetime', 'datetime_CAPI', 'sys', 'time', 'timedelta', 'timezone', 'tzinfo']

datetime 的成員大多是類別, 可以用下列模組中的 list_members() 函式來檢視成員類型 :

# members.py
import inspect 
def varname(x): 
    return [k for k,v in inspect.currentframe().f_back.f_locals.items() if v is x][0]
def list_members(parent_obj):
    members=dir(parent_obj)
    parent_obj_name=varname(parent_obj)       
    for mbr in members:
        child_obj=eval(parent_obj_name + '.' + mbr) 
        if not mbr.startswith('_'):
            print(mbr, type(child_obj))

參考 : 


將 members 模組放在目前工作目錄下匯入 list_members(), 於呼叫時傳入模組/套件/物件即可 :

>>> from members import list_members   
>>> list_members(datetime)    
MAXYEAR <class 'int'>
MINYEAR <class 'int'>
date <class 'type'>
datetime <class 'type'>
datetime_CAPI <class 'PyCapsule'>
sys <class 'module'>
time <class 'type'>
timedelta <class 'type'>
timezone <class 'type'>
tzinfo <class 'type'>

常用的有五個類別 :
  1. date : 處理日期之類別
  2. time : 處理時間之類別
  3. datetime : 處理日期與時間之類別
  4. timedelta : 處理時間差之類別
  5. timezone : 處理時區之類別
在資料科學中以 datetime 與 timedelta 類別最常用. 


一. 使用 datetime.date 類別處理日期 :

date 類別用來處理日期相關資訊, 先用 dir() 檢視類別成員 : 

>>> from datetime import date   
>>> dir(date)      
['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'ctime', 'day', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'min', 'month', 'replace', 'resolution', 'strftime', 'timetuple', 'today', 'toordinal', 'weekday', 'year']

用上面的自訂模組 members 之 list_members() 檢視 : 

>>> list_members(date)   
ctime <class 'method_descriptor'>
day <class 'getset_descriptor'>
fromisocalendar <class 'builtin_function_or_method'>
fromisoformat <class 'builtin_function_or_method'>
fromordinal <class 'builtin_function_or_method'>
fromtimestamp <class 'builtin_function_or_method'>
isocalendar <class 'method_descriptor'>
isoformat <class 'method_descriptor'>
isoweekday <class 'method_descriptor'>
max <class 'datetime.date'>
min <class 'datetime.date'>
month <class 'getset_descriptor'>
replace <class 'method_descriptor'>
resolution <class 'datetime.timedelta'>
strftime <class 'method_descriptor'>
timetuple <class 'method_descriptor'>
today <class 'builtin_function_or_method'>
toordinal <class 'method_descriptor'>
weekday <class 'method_descriptor'>
year <class 'getset_descriptor'>

其中有一個很常用的內建函式 today(), 此乃靜態方法毋須建立物件可直接呼叫, 它會傳回今日日期的 date 物件 : 

>>> d=date.today()     
>>> type(d)  
<class 'datetime.date'>  
>>> d    
datetime.date(2024, 8, 13)
>>> print(d)  
2024-08-13   

可以將 date 物件垂給 str() 轉成 'YYYY-mm-dd' 格式的 ISO 日期字串 :

>>> str(d)   
'2024-08-13'

如果要建立指定日期之 date 物件, 可以呼叫 datetime.date 類別的建構子 date() 並傳入 year, month, 與 day 三個參數即可 :

datetime.date(year, month, day)

例如 2024 年的元旦 :
  
>>> d=date(2024, 1, 1)   
>>> type(d)    
<class 'datetime.date'>     

用 dir() 檢視 date 物件成員 : 

>>> dir(d)   
['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'ctime', 'day', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'min', 'month', 'replace', 'resolution', 'strftime', 'timetuple', 'today', 'toordinal', 'weekday', 'year']

用上面的自訂模組 members 之 list_members() 檢視 date 物件成員 :

>>> list_members(d)   
ctime <class 'builtin_function_or_method'>
day <class 'int'>
fromisocalendar <class 'builtin_function_or_method'>
fromisoformat <class 'builtin_function_or_method'>
fromordinal <class 'builtin_function_or_method'>
fromtimestamp <class 'builtin_function_or_method'>
isocalendar <class 'builtin_function_or_method'>
isoformat <class 'builtin_function_or_method'>
isoweekday <class 'builtin_function_or_method'>
max <class 'datetime.date'>
min <class 'datetime.date'>
month <class 'int'>
replace <class 'builtin_function_or_method'>
resolution <class 'datetime.timedelta'>
strftime <class 'builtin_function_or_method'>
timetuple <class 'builtin_function_or_method'>
today <class 'builtin_function_or_method'>
toordinal <class 'builtin_function_or_method'>
weekday <class 'builtin_function_or_method'>
year <class 'int'>

可見 date 物件有非常多屬性與方法可用, 常用屬性與方法如下表 : 


 date 物件屬性  說明
 year  年
 month  月
 day  日


例如 : 

>>> d.year   
2024
>>> d.month   
1
>>> d.day   
1

常用方法如下表 : 


 date 物件常用方法  說明
 strftime(str)  依據格式字串 str (例如 '%Y-%m-%d') 傳回日期字串
 replace([year, month, day])  依據傳入參數更改 date 物件之年/月/日
 ctime()  傳回日期與時間字串 (時間固定為 00:00:00)
 weekday()  傳回此日為一周中的星期幾 (0~6), 星期一為 0
 isoweekday()  傳回此日為一周中的星期幾 (0~6), 星期一為 1
 isocalendar()  傳回 (年, 一年第幾周, ISO 的一周第幾日) tuple
 isoformat()  傳回 ISO 格式的日期時間字串 (即 'YYYY-mm-dd')
 today()  傳回今日之日期


以下測試均以 2024 年元旦的 date 物件 date(2024, 1, 1) 為例 : 

strftime() 方法會依據傳入之格式化字串傳回日期字串, 不過因為 date 物件僅有日期資訊, 因此時間部分固定為 00:00:00. 可用之格式化字串如下表所示 : 


 format 格式化字串 說明
 %a 星期的縮寫, 例如 Sun, Mon, Tue 等
 %A 星期的全寫, 例如 Sunday, Monday, Tuesday 等
 %b 月份的縮寫, 例如 Jan, Feb, Mar 等
 %B 月份的全寫, 例如 January, Feburary, March 等
 %c 本地之日期時間, 例如 'Sun Aug 28 13:17:18 2022'
 %d 一個月中的第幾日 (1~31)
 %H 24 小時制的時 (0~23), 例如 13 (下午一點)
 %I 12 小時制的時 (0~12), 例如 01 (下午一點或凌晨一點)
 %j 一年中的第幾日 (1~366)
 %m 數字月份 (1~12)
 %M 分鐘 (0~59)
 %p 上午 ('AM') 或下午 ('PM')
 %S 秒 (0~59)
 %U 一年中的第幾周 (0~53), 第一個星期日之前為第0 周 (週日為一周之始)
 %w 一周中的第幾天 (0~6), 週日為 0
 %W 一年中的第幾周 (0~53), 第一個星期一之前為第0 周 (週一為一周之始)
 %x 本地之日期, 格式=月/日/年(兩位), 例如 '08/28/22'
 %X 本地之日期, 格式=時:分:秒, 例如 '14:14:48'
 %y 無世紀之年份 (2 位數), 例如 '22' (表示 2022 年)
 %Y 有世紀之年份 (4 位數), 例如 '2022' (表示 2022 年)
 %z 相對於 GMT 的時區偏移值 (24 小時制), 例如台灣是 '+0800' 表示 GMT+8 
 %Z 時區名稱 (已棄用)
 %% 顯示 '%' 字元


這與 time 模組的 strftime() 方法所用之格式化字串完全相同, 參考 :


例如 : 

>>> d.strftime('%Y-%m-%d')   
'2024-01-01'   
>>> d.strftime('%Y/%m/%d')   
'2024/01/01'   

ctime() 方法傳回英文的日期字串 (但時間部分固定為 00:00:00) :

>>> d.ctime()    
'Mon Jan  1 00:00:00 2024'

weekday() 方法傳回此日為一周中的第幾日 (星期一為 0) :

>>> d.weekday()   
0

isoweekday() 傳回 ISO 一周中的第幾日 (星期一為 1) :

>>> d.isoweekday()   
1

isocalendar() 會傳回一個 IsoCalendarDate 物件, 其實就是一個由 (年份, 一年的第幾周, ISO 一周第幾日) 組成的 tuple, 例如 : 

>>> d.isocalendar()    
datetime.IsoCalendarDate(year=2024, week=1, weekday=1)
>>> d.isocalendar()[0]   
2024
>>> d.isocalendar()[1]   
1
>>> d.isocalendar()[2]   
1

isoformat() 方法會傳回 'YYYY-mm-dd' 的 ISO 日期字串 :

>>> d.isoformat()  
'2024-01-01'

today() 方法會傳回今日日期之 date 物件 :

>>> d    
datetime.date(2024, 1, 1)   
>>> d.today()   
datetime.date(2024, 8, 13)

可見雖然物件 d 的日期是 2024-01-01, 但呼叫其 today() 會傳回今日日期. 

replace() 方法可傳入 year, month, 或 day 來更改日期物件中的年, 月, 日, 例如 : 

>>> d.replace(year=2023)   
datetime.date(2023, 1, 1)   
>>> d.replace(year=2024, month=7, day=23)     
datetime.date(2024, 7, 23)
>>> d.replace(month=1, day=1)   
datetime.date(2024, 1, 1)  


二. 使用 datetime.time 類別處理時間 :

呼叫 time 類別的建構子 time() 即可建立 time 物件, 參數結構如下 :

time([hour=0, minute=0, second=0, microsecond=0, tzinfo=None])   

注意, 參數 tzinfo 預設為 UTC 時間. 

例如 : 

>>> t=time()        # 未傳入參數時間為 00:00
>>> t  
datetime.time(0, 0) 
>>> t=time(11, 10, 5, 1)     # 指定時分秒與微秒
>>> t     
datetime.time(11, 10, 5, 1)   
>>> type(t)     
<class 'datetime.time'>   

用 dir() 檢視 time 物件內容 :

>>> dir(t)   
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'dst', 'fold', 'fromisoformat', 'hour', 'isoformat', 'max', 'microsecond', 'min', 'minute', 'replace', 'resolution', 'second', 'strftime', 'tzinfo', 'tzname', 'utcoffset']

用上面的 list_members() 檢視內容 :

>>> list_members(t)   
dst <class 'builtin_function_or_method'>
fold <class 'int'>
fromisoformat <class 'builtin_function_or_method'>
hour <class 'int'>
isoformat <class 'builtin_function_or_method'>
max <class 'datetime.time'>
microsecond <class 'int'>
min <class 'datetime.time'>
minute <class 'int'>
replace <class 'builtin_function_or_method'>
resolution <class 'datetime.timedelta'>
second <class 'int'>
strftime <class 'builtin_function_or_method'>
tzinfo <class 'NoneType'>
tzname <class 'builtin_function_or_method'>
utcoffset <class 'builtin_function_or_method'>

time 物件常用屬性如下表 :


 time 物件常用屬性 說明
 hour 時
 minute 分
 second 秒
 microsecond 微秒
 min 最小時間 (0, 0)
 max 最大時間 (23, 59, 59, 999999)


例如 : 

>>> t=time(11, 10, 5, 1)  
>>> t.hour   
11
>>> t.minute   
10
>>> t.second   
5
>>> t.microsecond   
1
>>> t.min   
datetime.time(0, 0)
>>> t.max   
datetime.time(23, 59, 59, 999999) 

time 物件常用方法如下表 :


 time 物件常用方法 說明
 strftime(format_str) 依據格式字串 format_str (例如 '%H-%M-%S') 傳回時間字串
 replace([hour, minute, second]) 依據傳入參數更改 time 物件之時/分/秒/微秒
 fromisoformat(str) 以 ISO 格式之時間字串 (例如 '12:34:56') 建立新的 time 物件
 isoformat() 傳回 ISO 格式的時間字串 (即 'HH-MM-SS')


其中 strftime() 與 replace() 用法與上面 date 物件類似, 只是傳入參數不同. 注意, replace() 與 fromisoformat() 會傳回新的 time 物件, 不會更改原本的 time 物件內容. 

例如 : 

>>> t=time(hour=1, minute=23, second=56)    
>>> t    
datetime.time(1, 23, 56)   
>>> t.strftime('%H:%M:%S')    
'01:23:56'   
>>> t.replace(hour=8)  
datetime.time(8, 23, 56)
>>> t.replace(minute=11, second=46)    # 傳回新的 time 物件
datetime.time(1, 11, 46)
>>> t.isoformat()      # 原物件不受影響
'01:23:56'   
>>> t.fromisoformat('01:23:45')   
datetime.time(1, 23, 45)   
>>> t                          # 原物件不受影響
datetime.time(1, 23, 56)   
>>> t=t.fromisoformat('01:23:45')      # 覆蓋原物件
>>> t   
datetime.time(1, 23, 45)    


三. 使用 datetime.timedelta 類別處理時間差 :

timedelta 類別用來處理一段時間差 (time difference) 而非某個時間點, 呼叫其建構式 timedelta() 即可建立一個時間差 timedelta 物件, 參數結構如下 :

timedelta([weeks=0, days=0, hours=0, minutes=0, seconds=0, microseconds=0])    

注意, 每個關鍵字參數皆為 optional, 預設值均為 0. 最長的單位為周, 原因是周以下的長度都是固定的, 而年與月則否 (閏年與大月小月). 例如 :


>>> from datetime import timedelta  
>>> delta=timedelta(weeks=1, days=2, hours=3, minutes=4, seconds=5)    
>>> delta     
datetime.timedelta(days=9, seconds=11045)   
>>> type(delta)    
<class 'datetime.timedelta'>   

總天數是 7+2=9 天, 其餘 3 小時 4 分 5 秒換算成 3*60*60 + 4*60 + 5=11045 秒.

用 dir() 檢視 timedelta 物件內容 :

>>> dir(delta)   
['__abs__', '__add__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', 'days', 'max', 'microseconds', 'min', 'resolution', 'seconds', 'total_seconds']

用自訂函式 list_members() 檢視內容 :

>>> list_members(delta)    
days <class 'int'>
max <class 'datetime.timedelta'>
microseconds <class 'int'>
min <class 'datetime.timedelta'>
resolution <class 'datetime.timedelta'>
seconds <class 'int'>
total_seconds <class 'builtin_function_or_method'>

timedelta 物件屬性如下表 :


 timedelta 物件屬性 說明
 days 日數
 seconds 秒數
 microseconds 微秒數
 resolution 1 微秒的 timedelta 物件
 min 最小時間差 (-999999999 日)
 max 最大時間差 (999999999 日, 86399 秒, 999999 微秒)


例如 :

>>> delta.days   
9
>>> delta.seconds  
11045
>>> delta.microseconds 
0
>>> delta.resolution    
datetime.timedelta(microseconds=1)  
>>> delta.min 
datetime.timedelta(days=-999999999)
>>> delta.max     
datetime.timedelta(days=999999999, seconds=86399, microseconds=999999)  

timedelta 物件只有一個方法 : 


 timedelta 物件方法 說明
 total_seconds() 傳回總秒數


例如 :

>>> delta.total_seconds()   
788645.0

timedelta 物件彼此可以作算術運算, 例如 :

>>> delta1=timedelta(days=30)   
>>> delta1   
datetime.timedelta(days=30)   
>>> delta2=timedelta(weeks=2)   
>>> delta2   
datetime.timedelta(days=14)
>>> delta1-delta2   
datetime.timedelta(days=16)


四. 使用 datetime.datetime 類別處理日期時間 :

datetime 類別主要用來處理日期時間, 並可與 timedelta 進行時間差的算術運算. 

先檢視 datetime 類別內容 :

>>> from datetime import datetime   
>>> dir(datetime)    
['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'astimezone', 'combine', 'ctime', 'date', 'day', 'dst', 'fold', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'hour', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'microsecond', 'min', 'minute', 'month', 'now', 'replace', 'resolution', 'second', 'strftime', 'strptime', 'time', 'timestamp', 'timetuple', 'timetz', 'today', 'toordinal', 'tzinfo', 'tzname', 'utcfromtimestamp', 'utcnow', 'utcoffset', 'utctimetuple', 'weekday', 'year']

用自訂函式 list_members() 檢視內容 :

>>> list_members(datetime)    
astimezone <class 'method_descriptor'>
combine <class 'builtin_function_or_method'>
ctime <class 'method_descriptor'>
date <class 'method_descriptor'>
day <class 'getset_descriptor'>
dst <class 'method_descriptor'>
fold <class 'getset_descriptor'>
fromisocalendar <class 'builtin_function_or_method'>
fromisoformat <class 'builtin_function_or_method'>
fromordinal <class 'builtin_function_or_method'>
fromtimestamp <class 'builtin_function_or_method'>
hour <class 'getset_descriptor'>
isocalendar <class 'method_descriptor'>
isoformat <class 'method_descriptor'>
isoweekday <class 'method_descriptor'>
max <class 'datetime.datetime'>
microsecond <class 'getset_descriptor'>
min <class 'datetime.datetime'>
minute <class 'getset_descriptor'>
month <class 'getset_descriptor'>
now <class 'builtin_function_or_method'>
replace <class 'method_descriptor'>
resolution <class 'datetime.timedelta'>
second <class 'getset_descriptor'>
strftime <class 'method_descriptor'>
strptime <class 'builtin_function_or_method'>
time <class 'method_descriptor'>
timestamp <class 'method_descriptor'>
timetuple <class 'method_descriptor'>
timetz <class 'method_descriptor'>
today <class 'builtin_function_or_method'>
toordinal <class 'method_descriptor'>
tzinfo <class 'getset_descriptor'>
tzname <class 'method_descriptor'>
utcfromtimestamp <class 'builtin_function_or_method'>
utcnow <class 'builtin_function_or_method'>
utcoffset <class 'method_descriptor'>
utctimetuple <class 'method_descriptor'>
weekday <class 'method_descriptor'>
year <class 'getset_descriptor'>

此類別有 4 個很常用的靜態方法, 毋須建立物件即可呼叫 :


 datetime 類別常用靜態方法 說明
 today() 傳回今日之日期時間物件
 now() 傳回現在之日期時間物件
 strptime(datetime_str, format_str) 將日期時間字串依據格式化字串轉成 datetime 物件
 fromtimestamp(stamp) 將時戳轉成 datetime 物件


這 4 個靜態方法都會傳回一個 datetime 物件, 例如 :

>>> datetime.today()     
datetime.datetime(2024, 8, 14, 23, 22, 54, 895153)
>>> datetime.now()    
datetime.datetime(2024, 8, 14, 23, 23, 11, 207245)
>>> datetime.strptime('2024-08-14', '%Y-%m-%d')     
datetime.datetime(2024, 8, 14, 0, 0)    
>>> datetime.strptime('2024-08-14 23:23:11', '%Y-%m-%d %H:%M:%S')    
datetime.datetime(2024, 8, 14, 23, 23, 11)
>>> datetime.fromtimestamp(1723704694)   
datetime.datetime(2024, 8, 15, 14, 51, 34)

可見其實 today() 與 now() 會傳回相同結果. 傳給 fromtimestamp() 的時戳可用 time 模組的 time() 方法查得 : 

>>> import time  
>>> time.time()   
1723704694.3911824  

也可以呼叫建構子 datetime() 並傳入日期與時間參數來建立 datetime 物件 :

datetime(year, month, day [, hour=0, minute=0, second=0, microsecond=0, tzinfo=None])    

注意, 此建構式必須傳入年月日這 3 個必要位置/關鍵字參數, 其餘時分秒微秒等參數可有可無, 例如 :

>>> dt=datetime(2024, 8, 14)      # 傳入位置參數 (順序為年, 月, 日)
>>> dt   
datetime.datetime(2024, 8, 14, 0, 0)   
>>> dt=datetime(year=2024, month=8, day=14)    # 傳入關鍵字參數 (順序可變)
>>> dt   
datetime.datetime(2024, 8, 14, 0, 0)   
>>> datetime(2024, 8, 14, 23, 49, 23)      # 有傳入時分秒
datetime.datetime(2024, 8, 14, 23, 49, 23)  
>>> datetime(2024, 8, 14, 23, 49, 23, 45634)      # 有傳入微秒
datetime.datetime(2024, 8, 14, 23, 49, 23, 45634)   

用 dir() 檢視 datetime 物件內容 :

>>> dir(dt)   
['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'astimezone', 'combine', 'ctime', 'date', 'day', 'dst', 'fold', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'hour', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'microsecond', 'min', 'minute', 'month', 'now', 'replace', 'resolution', 'second', 'strftime', 'strptime', 'time', 'timestamp', 'timetuple', 'timetz', 'today', 'toordinal', 'tzinfo', 'tzname', 'utcfromtimestamp', 'utcnow', 'utcoffset', 'utctimetuple', 'weekday', 'year']

用 list_members() 檢視 datetime 物件內容 :

>>> list_members(dt)   
astimezone <class 'builtin_function_or_method'>
combine <class 'builtin_function_or_method'>
ctime <class 'builtin_function_or_method'>
date <class 'builtin_function_or_method'>
day <class 'int'>
dst <class 'builtin_function_or_method'>
fold <class 'int'>
fromisocalendar <class 'builtin_function_or_method'>
fromisoformat <class 'builtin_function_or_method'>
fromordinal <class 'builtin_function_or_method'>
fromtimestamp <class 'builtin_function_or_method'>
hour <class 'int'>
isocalendar <class 'builtin_function_or_method'>
isoformat <class 'builtin_function_or_method'>
isoweekday <class 'builtin_function_or_method'>
max <class 'datetime.datetime'>
microsecond <class 'int'>
min <class 'datetime.datetime'>
minute <class 'int'>
month <class 'int'>
now <class 'builtin_function_or_method'>
replace <class 'builtin_function_or_method'>
resolution <class 'datetime.timedelta'>
second <class 'int'>
strftime <class 'builtin_function_or_method'>
strptime <class 'builtin_function_or_method'>
time <class 'builtin_function_or_method'>
timestamp <class 'builtin_function_or_method'>
timetuple <class 'builtin_function_or_method'>
timetz <class 'builtin_function_or_method'>
today <class 'builtin_function_or_method'>
toordinal <class 'builtin_function_or_method'>
tzinfo <class 'NoneType'>
tzname <class 'builtin_function_or_method'>
utcfromtimestamp <class 'builtin_function_or_method'>
utcnow <class 'builtin_function_or_method'>
utcoffset <class 'builtin_function_or_method'>
utctimetuple <class 'builtin_function_or_method'>
weekday <class 'builtin_function_or_method'>
year <class 'int'>

datetime 物件常用屬性如下表 :


 datetime 物件常用屬性 說明
 year 年
 month 月
 day 日
 hour 時
 minute 月
 second 日
 microsecond 年
 min 最小值
 max 最大值


例如 : 

>>> dt=datetime.today()   
>>> dt  
datetime.datetime(2024, 8, 15, 9, 47, 50, 323888)
>>> dt.year 
2024
>>> dt.month   
8
>>> dt.day 
15
>>> dt.hour  
9
>>> dt.minute   
47
>>> dt.second   
50
>>> dt.microsecond  
323888
>>> dt.min    
datetime.datetime(1, 1, 1, 0, 0)
>>> dt.max    
datetime.datetime(9999, 12, 31, 23, 59, 59, 999999)

datetime 物件常用方法如下表 : 


 datetime 物件常用方法 說明
 strftime(format_str) 依據格式字串 (例如 '%Y-%m-%d %H:%M:%S') 傳回日期時間字串
 strptime(dt_str, format_str) 將日期時間字串 dt_str 依格式字串 format_str 解析傳回 datetime 物件
 replace([year, month, ...]) 依據傳入日期時間參數更改 datetime 物件之年/月/日/時/分/秒/微秒
 ctime() 傳回日期與時間字串
 weekday() 傳回此日為一周中的星期幾 (0~6), 星期一為 0
 isoweekday() 傳回此日為一周中的星期幾 (0~6), 星期一為 1
 isocalendar() 傳回 (年, 一年第幾周, ISO 的一周第幾日) tuple
 isoformat() 傳回 ISO 格式的日期時間字串 (即 'YYYY-mm-ddTHH:MM::SS.uuuuu')
 today() 傳回今日之日期時間 (即時)
 now() 傳回現在之日期時間 (即時)
 timetuple() 傳回


例如 :

>>> dt=datetime.today()    # 或用 now() 亦可 
>>> dt.ctime()                      # 英文日期時間
'Thu Aug 15 10:04:35 2024'
>>> dt.weekday()                # 星期四傳回 3
3
>>> dt.isoweekday()           # 星期四傳回 4
4
>>> dt.isoformat()      
'2024-08-15T10:04:35.271479'   
>>> dt.isocalendar()    
datetime.IsoCalendarDate(year=2024, week=33, weekday=4)   
>>> dt.today()           # 與 dt 物件無關的即時日期時間
datetime.datetime(2024, 8, 15, 10, 8, 36, 315497)
>>> dt.now()             # 與 dt 物件無關的即時日期時間
datetime.datetime(2024, 8, 15, 10, 9, 21, 897006)
>>> dt.timetuple()   
time.struct_time(tm_year=2024, tm_mon=8, tm_mday=15, tm_hour=10, tm_min=4, tm_sec=35, tm_wday=3, tm_yday=228, tm_isdst=-1)
>>> dt.replace(year=2023, day=24)       # 更改年, 日
datetime.datetime(2023, 8, 24, 10, 4, 35, 271479)
>>> dt.replace(hour=20, second=59)     # 更改時, 秒
datetime.datetime(2024, 8, 15, 20, 4, 59, 271479)

在實務中最常用的方法是 strftime() 與 strptime(), 兩者互為反運算, strftime() 將 datetime 物件依照格式化字串之格式輸出; 後者則是將日期時間字串依照格式化字串轉成 datetime 物件, 例如 : 

>>> dt.strftime('%Y-%m-%d %H:%M:%S.%f')    
'2024-08-15 10:04:35.271479'
>>> dt.strftime('%I:%M %p')   
'10:04 AM'
>>> dt.strftime('%B of %y')   
'August of 24'
>>> dt.strptime('2024-08-15 10:04:35.271479', '%Y-%m-%d %H:%M:%S.%f')   
datetime.datetime(2024, 8, 15, 10, 4, 35, 271479)
>>> dt.strptime('10:04:35', '%H:%M:%S')    # 未指定年月日預設 1900/1/1
datetime.datetime(1900, 1, 1, 10, 4, 35)
>>> dt.strptime('August 15, 2024', '%B %d, %Y')   
datetime.datetime(2024, 8, 15, 0, 0)

注意, 雖然 strftime() 與 strptime() 都同時定義在 datetime.datetime 類別中, 但只有 strptime() 是可以在不建立物件情況下直接呼叫的靜態方法, strftime() 則是必須先建立物件才能呼叫的物件方法, 例如上面將 '2024-08-15 10:04:35.271479' 轉成 datetime 物件的範例也可以直接呼叫 datetime.strptime() :

>>> from datetime import datetime    
>>> datetime.strptime('2024-08-15 10:04:35.271479', '%Y-%m-%d %H:%M:%S.%f')    
datetime.datetime(2024, 8, 15, 10, 4, 35, 271479)   

但如果要將 datetime 物件格式化為日期時間字串, 那前提必須是已建立了 datetime 物件. 

datetime 物件之間可以進行算術運算, 兩個 datetime 物件相減會傳回一個 timedelta 物件 : 

>>> dt1=datetime(2024, 1, 1)  
>>> dt1  
datetime.datetime(2024, 1, 1, 0, 0)
>>> dt2=datetime(2024, 8, 15)    
>>> dt2    
datetime.datetime(2024, 8, 15, 0, 0)
>>> dt2-dt1                                # 兩個 datetime 物件相減得到 timedelta 物件
datetime.timedelta(days=227)    # 元旦至 8/15 差距為 227 天
>>> type(dt2-dt1)   
<class 'datetime.timedelta'>

datetime 物件最方便的功能是可以搭配 timedelta 物件進行時間差的算術運算 : 

>>> dt=datetime.today()   
>>> dt    
datetime.datetime(2024, 8, 15, 12, 46, 12, 194439)   
>>> dt + timedelta(hours=3)     
datetime.datetime(2024, 8, 15, 15, 46, 12, 194439)
>>> dt - timedelta(days=3)
datetime.datetime(2024, 8, 12, 12, 46, 12, 194439)
>>> dt - timedelta(weeks=1)
datetime.datetime(2024, 8, 8, 12, 46, 12, 194439)

如果要計算 100 天後的日期是哪天, 可以將今日之 datetime 物件加上 timedelta(days=100) :

>>> datetime.today()   
datetime.datetime(2024, 8, 15, 14, 58, 12, 696363)
>>> datetime.today() + timedelta(days=100)     
datetime.datetime(2024, 11, 23, 14, 58, 33, 754958)

可見 8/15 的 100 天後為 11/23 日. 

沒有留言 :