datetime?timedelta?timeモジュールとの違い?、、Pythonのdatetimeと関連モジュールを整理する
Pythonでの日時操作について、今まで理解を怠っていたが、改めて公式ドキュメントを読んでそれぞれのモジュールの使い方と違いを理解した
※ 全てPython3.9の標準ライブラリの範囲内
datetimeモジュール
「datetime」は日付や時間を扱うための一番基本のモジュール
datetimeでタイムゾーン情報を持つものはaware、持たないものはnativeと言う(=「tzinfo」で何かしら指定されているかどうか)
awareとnativeが混ざった状態では計算できない
公式ドキュメントに書いてある通りだが、datetimeはいくつかデータ型を提供していて、まとめると以下の通り
データ型 | 説明 | 書き方 | 書き方例 | 書き方例のprint結果 |
---|---|---|---|---|
date | 日付 | datetime.date(【year】, 【month】, 【day】) | datetime.date(1990, 7, 2) | 1990-07-02 |
time | 時間 | datetime.time(【hour】, 【minute】, 【second】, 【microsecond】, 【tzinfo】) | datetime.time(16, 30, 20, 79060, tzinfo=zoneinfo.ZoneInfo(“Asia/Tokyo”)) | 16:30:20.079060 |
datetime | 日付と時間 | datetime.datetime(【year】, 【month】, 【day】, 【hour】, 【minute】, 【second】, 【microsecond】, 【tzinfo】) | datetime.datetime(1990, 7, 2, 16, 30, 20, 79060, tzinfo=zoneinfo.ZoneInfo(“Asia/Tokyo”)) | 1990-07-02 16:30:20.079060 |
timedelta | date/datetimeなどの差 | 【date/datetime型】-【date/datetime型】 など |
datetime.date(2022, 9, 29) – datetime.date(1990, 7, 2) | 11777 days, 0:00:00 |
datetime型で時間を指定しなければ「ゼロ(00:00:00)」になる
tzinfoに何も指定しないと「None」になる
以下はコード例と出力結果
(zoneinfoモジュールについては後述)
% cat datetime_work.py import datetime import zoneinfo print("=====date型=====") type_date = datetime.date(1990, 7, 2) print(type_date) print(type(type_date)) print("=====time型=====") type_time = datetime.time(16, 30, 20, 79060, tzinfo=zoneinfo.ZoneInfo("Asia/Tokyo")) print(type_time) print(type_time.tzinfo) print(type(type_time)) print("=====datetime型=====") type_datetime = datetime.datetime(1990, 7, 2, 16, 30, 20, 79060) print(type_datetime) print(type_datetime.tzinfo) print(type(type_datetime)) print("=====timedelta型=====") type_timedelta = datetime.date(2022, 9, 29) - datetime.date(1990, 7, 2) print(type_timedelta) print(type(type_timedelta))
% python datetime_work.py =====date型===== 1990-07-02 <class 'datetime.date'> =====time型===== 16:30:20.079060 Asia/Tokyo <class 'datetime.time'> =====datetime型===== 1990-07-02 16:30:20.079060 None <class 'datetime.datetime'> =====timedelta型===== 11777 days, 0:00:00 <class 'datetime.timedelta'>
print結果を整形したい場合は、strftime(datetime→str)と strptime(str→datetime)を使う
以下の例では、strftimeで、datetime型のtype_datetimeを「%Y/%m/%d %H:%M:%S」という形式のstr型に変換した後、strptimeでdatetime型に再び戻している
type_datetime = datetime.datetime(1990, 7, 2, 16, 30, 20, 79060) print(type_datetime) print(type(type_datetime)) print("=====strftimeを使ってdatetime型からstr型へ変換=====") type_str = type_datetime.strftime("%Y/%m/%d %H:%M:%S") print(type_str) print(type(type_str)) print("=====strptimeを使ってstr型からdatetime型へ変換=====") type_datetime_2 = datetime.datetime.strptime(type_str, "%Y/%m/%d %H:%M:%S") print(type_datetime_2) print(type(type_datetime_2))
1990-07-02 16:30:20.079060 <class 'datetime.datetime'> =====strftimeを使ってdatetime型からstr型へ変換===== 1990/07/02 16:30:20 <class 'str'> =====strptimeを使ってstr型からdatetime型へ変換===== 1990-07-02 16:30:20 <class 'datetime.datetime'>
zoneinfoモジュール
「zoneinfo」はPythonバージョン3.9で追加されたモジュールで、tzinfoの指定をする
上のdatetimeモジュールのコード例で言うと、この部分で使っている
print("=====time型=====") type_time = datetime.time(16, 30, 20, 79060, tzinfo=zoneinfo.ZoneInfo("Asia/Tokyo")) print(type_time) print(type_time.tzinfo) print(type(type_time))
※ 出力結果
=====time型===== 16:30:20.079060 Asia/Tokyo <class 'datetime.time'>
Pythonバージョン3.9以前であれば、timedelta型で指定したり、deteutilやpytzなどのサードパーティのモジュールを使う
例えば上のコードをtimedelta型に書き換えると以下の通り
print("=====timedeltaを使ってtzinfoを指定する=====") #type_time = datetime.time(16, 30, 20, 79060, tzinfo=zoneinfo.ZoneInfo("Asia/Tokyo")) type_time = datetime.time(16, 30, 20, 79060, tzinfo=datetime.timezone(datetime.timedelta(hours=+9), "Asia/Tokyo")) print(type_time) print(type_time.tzinfo) print(type(type_time))
※ 出力結果
=====timedeltaを使ってtzinfoを指定する===== 16:30:20.079060+09:00 Asia/Tokyo <class 'datetime.time'>
“Asia/Tokyo”はUTC+9だから、、と指定しなければならず、少し面倒、、
故に、deteutilやpytzなどのモジュールがあるのだと思われる
まあ、3.9からは何も考えずzoneinfoを使うのが良さそう
timeモジュール
次はtimeモジュール
今までは、time.sleepでしかお世話になっていなかったが、実は色々な使い方があった
正直、公式ドキュメントを読んだだけでは、datetimeとの使い分け方をしっかり理解できた訳ではないが、より時刻操作をしたいのであればtimeモジュールを使うのが良いと思われる
timeモジュールでは、localtimeなどで取得した時刻は「struct_time型」という型として返される
struct_time型で返された時刻は、strftimeを使ってstr型に変換できる
% cat time_work.py import time print("=====現在のlocal時間の取得=====") local_time = time.localtime() print(local_time) print(type(local_time)) print("=====struct_time型→str型への変換=====") type_str = time.strftime("%Y/%m/%d %H:%M:%S", local_time) print(type_str) print(type(type_str)) print("=====str型→struct_time型への変換=====") type_struct_time = time.strptime(type_str, "%Y/%m/%d %H:%M:%S") print(type_struct_time) print(type(type_struct_time))
% python time_work.py =====現在のlocal時間の取得===== time.struct_time(tm_year=2022, tm_mon=9, tm_mday=30, tm_hour=0, tm_min=14, tm_sec=57, tm_wday=4, tm_yday=273, tm_isdst=0) <class 'time.struct_time'> =====struct_time型→str型への変換===== 2022/09/30 00:14:57 <class 'str'> =====str型→struct_time型への変換===== time.struct_time(tm_year=2022, tm_mon=9, tm_mday=30, tm_hour=0, tm_min=14, tm_sec=57, tm_wday=4, tm_yday=273, tm_isdst=-1) <class 'time.struct_time'>
calendarモジュール
calendarモジュールについては、「カレンダーを出力してくれるモジュールでしょ(いつ使うん?)」くらいの知識だったが、datetime.date型で返してくれるメソッドが結構あったので試しに動かしてみた
% cat calendar_work.py import calendar print("=====calendar出力=====") print(calendar.month(2022, 9)) print("=====datetime.date型で週リスト出力=====") C = calendar.Calendar(firstweekday=0) print(C.monthdatescalendar(2022, 9))
% python calendar_work.py =====calendar出力===== September 2022 Mo Tu We Th Fr Sa Su 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 =====datetime.date型で週リスト出力===== [[datetime.date(2022, 8, 29), datetime.date(2022, 8, 30), datetime.date(2022, 8, 31), datetime.date(2022, 9, 1), datetime.date(2022, 9, 2), datetime.date(2022, 9, 3), datetime.date(2022, 9, 4)], [datetime.date(2022, 9, 5), datetime.date(2022, 9, 6), datetime.date(2022, 9, 7), datetime.date(2022, 9, 8), datetime.date(2022, 9, 9), datetime.date(2022, 9, 10), datetime.date(2022, 9, 11)], [datetime.date(2022, 9, 12), datetime.date(2022, 9, 13), datetime.date(2022, 9, 14), datetime.date(2022, 9, 15), datetime.date(2022, 9, 16), datetime.date(2022, 9, 17), datetime.date(2022, 9, 18)], [datetime.date(2022, 9, 19), datetime.date(2022, 9, 20), datetime.date(2022, 9, 21), datetime.date(2022, 9, 22), datetime.date(2022, 9, 23), datetime.date(2022, 9, 24), datetime.date(2022, 9, 25)], [datetime.date(2022, 9, 26), datetime.date(2022, 9, 27), datetime.date(2022, 9, 28), datetime.date(2022, 9, 29), datetime.date(2022, 9, 30), datetime.date(2022, 10, 1), datetime.date(2022, 10, 2)]]
これでdatetimeと関連モジュール周りについてなんとなく違いが理解できた
以上。