You are instructed to email the weekly report at the beginning of the week.

if jpholiday.is_holiday (today) == True:
    sys.exit ()
if today.weekday () == 0 or today.weekday () == 1 and jpholiday.is_holiday (today + datetime.timedelta (days = -1)) == True:

I think that this is almost enough, but if it is this, it will not be delivered on Wednesday and Thursday after consecutive holidays such as Golden Week.
"Wednesday/Thursday after consecutive holidays" can be judged by adding more if statements or if statements.
Prepare a list of days to run on Wednesdays and Thursdays,
Is there any smart way to do it?
If not, I think it is safer to say "deliver on Mondays regardless of holidays" or turn off the machine during consecutive holidays and manually run the program on exceptional days.

  • Answer # 1

    Do you want to judge the "dawn" of consecutive holidays for e-mail newsletter (?) Delivery?
    Is it one way to have "after the Golden Week holidays" as data more honestly?
    Delivery conditions can be defined by the conditions of "Monday, not a holiday" or "Day after consecutive holidays".

  • Answer # 2

    Answer using jpholiday.

    import datetime
    import jpholiday
    def get_first_weekday_date (base_date):
        monday = base_date --datetime.timedelta (days = base_date.weekday ())
        for i in range (7):
            dt = monday + datetime.timedelta (days = i)
            if jpholiday.is_holiday (dt):
                # print (f "skipped {dt} {jpholiday.is_holiday_name (dt)}")
            return dt
        return None # If the whole week is holiday
    today = datetime.date.today ()
    # today = datetime.date (2020, 5, 5) #for testing
    target_date = get_first_weekday_date (today)
    print (target_date)
    if target_date == today:
        print ("Now is the time ♪")

  • Answer # 3

    It is faster to make it anymore.

    jpholiday seems to be maintained, but I don't feel that it is a commonly used library. Also, it seems that special holidays can be added, but it seems that the base holiday cannot be deleted, so the company of the questioner said, "Next Monday's transfer holiday will be adjusted to work day by year!" May not be able to handle it.

    Also, although it is troublesome at first, I think that making it like this has the following merits.

    When you need to register next year's schedule or revise this year's schedule, it is easy to register (you can register the company holiday list or your own year holiday as it is, change something else You don't have to worry about registration, such as registering your day)

    It is easy to expand in the future when another requirement such as "Submit a provisional version of the weekly report on a weekend other than a holiday!"

    Defining a file on the outside is no longer an application, so please customize it yourself. Since terateil is a place for programmers to solve problems, instead of "answers that you don't have to look at the code after it is completed", "answers that can be incorporated into the questioner's code and expanded steadily" I kept in mind.

    class MyDateTime:
        # Prioritize upper set of days, ignore lower duplicated elements.
        # Of courese, you must register the future calendars,
        # in odrder not to work on many days! :-)
        special_workdays = {}
        special_holidays = {
            '2020-1-2', '2020-1-3', '2020-8-11', '2020-8-12', '2020-8-13', '2020-8-14',
            '2020-12-29', '2020-12-30', '2020-12-31'
        national_holidays = {
            '2020-1-1', '2020-1-13', '2020-2-11', '2020-2-23', '2020-2-24',
            '2020-3-20', '2020-4-29', '2020-5-3', '2020-5-4', '2020-5-5', '2020-5-6',
            '2020-7-23', '2020-7-24', '2020-8-10', '2020-9-21', '2020-9-22',
            '2020-11-3', '2020-11-23'
        def strptime (cls, s):
            tdatetime = datetime.datetime.strptime (s,'% Y-% m-% d')
            return datetime.date (tdatetime.year, tdatetime.month, tdatetime.day)
        def is_workday (cls, day):
            if day in map (cls.strptime, cls.special_workdays):
                return True
            if day in map (cls.strptime, cls.special_holidays):
                return False
            if day in map (cls.strptime, cls.national_holidays):
                return False
            return not (day.weekday () == 5 or day.weekday () == 6)
        def is_holiday (cls, day):
            return not cls.is_workday (day)
        def is_sad_day (cls, day): # the 1st workday of the week
            for i in range (day.weekday ()):
                if cls.is_workday (day --datetime.timedelta (days = day.weekday ()-i)):
                    return False
            return cls.is_workday (day)
    for day in ['2020-11-21', '2020-11-22', '2020-11-23', '2020-11-24', '2020-11-25']:
        print (day,'= sad day?', MyDateTime.is_sad_day (MyDateTime.strptime (day)))
    # 2020-11-21 = sad day? False
    # 2020-11-22 = sad day? False
    # 2020-11-23 = sad day? False
    # 2020-11-24 = sad day? True
    # 2020-11-25 = sad day? False