プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2022/01/18

[Python] 月初日、月末日、翌月の月初日の取得

event_note2022/01/18 0:03

日時を扱っていると月初日や月末日を取得したいということもあるので、そのやり方です。

やり方はいろいろあるかもしれませんが、あくまで一例ということで。

月初日

from datetime import datetime

dt = datetime.now()
print(dt)

first_dt = dt.replace(day=1)
print(first_dt)

first_dt = datetime(dt.year, dt.month, 1)
print(first_dt)
2022-01-17 15:55:25.492664
2022-01-01 15:55:25.492664
2022-01-01 00:00:00

時刻を保持したい場合は replace で日だけ置き換えればOKです。
時刻をクリアしたい場合は年月日を指定して新たに datetime を作成すればOKです。

月末日

calendar モジュールを使えば簡単にできます。
monthrange は指定した年月の初日の曜日と日数を返してくれます。
これを使って月初日と同じように取得できます。

from datetime import datetime
import calendar

dt = datetime.now()
print(dt)
  
day_of_week, last_day = calendar.monthrange(dt.year, dt.month)

last_dt = dt.replace(day=last_day)
print(last_dt)

last_dt = datetime(dt.year, dt.month, last_day)
print(last_dt)
2022-01-17 16:04:31.007994
2022-01-31 16:04:31.008065
2022-01-31 00:00:00

翌月の月初日

やり方としては以下の2通りがあります。

calendar と timedelta を使う方法

calendar.monthrange を使えば前述した方法で月末日が取得できるので、ここから timedelta を使って一日足してやれば、翌月の月初日が取得できます。

from datetime import datetime, timedelta
import calendar

dt = datetime.now()
print(dt)

day_of_week, last_day = calendar.monthrange(dt.year, dt.month)

next_first_dt = dt.replace(day=last_day) + timedelta(days=1)
print(next_first_dt)

next_first_dt = datetime(dt.year, dt.month, last_day) + timedelta(days=1)
print(next_first_dt)
2022-01-17 16:37:09.969484
2022-02-01 16:37:09.969484
2022-02-01 00:00:00

dateutil.relativedelta を使う方法

まず python-dateutil をインストールする必要があります。

$ pip install python-dateutil

dateutil.relativedelta を使えば一ヶ月後の日時が取得できるので、そこから前述した方法と同じように月初日が取得できます。

from datetime import datetime
from dateutil.relativedelta import relativedelta

dt = datetime.now()
print(dt)

next_dt = dt + relativedelta(months=1)

next_first_dt = next_dt.replace(day=1)
print(next_first_dt)

next_first_dt = datetime(next_dt.year, next_dt.month, 1)
print(next_first_dt)
2022-01-17 16:42:25.298845
2022-02-01 16:42:25.298845
2022-02-01 00:00:00

所感

標準モジュールだけで実装したい場合は calendartimedelta を使って実装すればいいですが、翌々月とか数ヶ月後とかも扱うのであれば dateutil.relativedelta を使ったほうが楽だと思いました。