M-Y-Y
@M-Y-Y

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

土日祝を考慮した日付判定ロジック

「本来はその月の16日以外はNGだけど、16日が土日祝の場合以降最初の平日ならOK」
という処理を色々かんがえて書いてみたのですが、もっとスッキリわかりやすく書ける気がしています。
よろしければアドバイスをいただけないでしょうか…?

(17日以降の場合だけ切り出しているのでjoining_dateに16日以前は入らないものとしてください…)

import datetime
from dateutil.relativedelta import relativedelta
import jpholiday


def is_head_of_month(joining_date, head_of_month):
    for n in range(1,5):
        next_day = head_of_month + relativedelta(days=n)

        if next_day.day == joining_date.day - 1:
            if next_day.weekday() == 5 or next_day.weekday() == 6 or jpholiday.is_holiday(next_day):  
                return True
            else:
                return False
    else:
        return False

join=datetime.date(2023, 9, 19)
head = datetime.date(2023, 9, 16)

if is_head_of_month(join, head):
    print("月度頭")
else:
    print("月度頭じゃない")

#  → 月度頭 

0

3Answer

先に結論から申しますと単に直近の平日を取得すればよいと思います.

def get_first_weekday(origin):
    for n in range(14): #ふつうは1週間以内にループを抜けると思うけど
        target_day = origin + relativedelta(days=n)
        if target_day.weekday() != 5 and target_day.weekday() != 6 and not jpholiday.is_holiday(target_day):
            return target_day
    return None

head = datetime.date(2023, 9, 16)
print(get_first_weekday(head) == datetime.date(2023,9,19))
# Expected 'True'

「月初めかどうか判定する」関数のユースケースを考えると「月初めがいつかは簡単に分かってたほうが便利じゃね?」てわけでそこだけを関数化した感じです.

ロジックのシンプルさというより関数の役割分担,もっと言うと抽象化を意識すると,コードの可読性を上げることができます.

2Like

土日祝の場合以降最初の日
は17日でしょうか?

17日を先に月曜~金曜の判定をし、
16日を土日祝日判定してはどうでしょうか?

1Like

お二方ともありがとうございました。
初心者の癖に頭が固くてお恥ずかしいです…。
以後もやりたいことを愚直に書くのではなく抽象化を意識していきます🙇

1Like

Your answer might help someone💌