How to calculate the first Monday of the month; python 3.3+

Question:

I need to run a monthly report on the first Monday of the month and calculate this day with Python. The code I have so far will go into a module in our ETL program and will determine if the date is actually the first day of the month. Ideally, what I need is if the Monday is the first Monday of the month, run the report (execute = 1) only on this day. Otherwise, do not run anything (execute = 0). What I have:

# Calculate first Monday of the month

# import module(s)

from datetime import datetime, date, timedelta

today = date.today() # - timedelta(days = 1)
datee = datetime.strptime(str(today), "%Y-%m-%d")

print(f'Today: {today}')

# function finds first Monday of the month given the date passed in "today"

def find_first_monday(year, month, day):
    d = datetime(year, int(month), int(day))
    offset = 0-d.weekday() #weekday = 0 means monday
    if offset < 0:
        offset+=7
    return d+timedelta(offset)

# converts datetime object to date
first_monday_of_month = find_first_monday(datee.year, datee.month, datee.day).date()

# prints the next Monday given the date that is passed as "today" 

print(f'Today's date: {today}')
print(f'First Monday of the month date: {first_monday_of_month}')

# if first Monday is true, execute = 1, else execute = 0; 1 will execute the next module of code

if today == first_monday_of_month:
  execute = 1
  print(execute) 
else:
  execute = 0
  print(execute)

It works assuming the date in "today" is not after the first Monday of the month. When "today" is after the first Monday of the month, it prints the next coming Monday.

Our ETL scheduler allows us to run daily, weekly, or monthly. I’m thinking I’ll have to run this daily, even though this is a monthly report, and the module with this code will determine if "today" is the first Monday of the month or not. If it’s not the first Monday, it will not execute the next code modules (execute = 0). I’m not confident this will actually run if "today" is the first Monday of the month since it prints the next coming Monday for any date passed in "today."

I can’t seem to find the answer I need for making sure it only calculates the first Monday of the month and only runs the report on that day. Thanks in advance.

Asked By: bcoble

||

Answers:

One way to do this is to ignore the passed in day value, and just use 7 instead; then you can simply subtract the weekday offset:

def find_first_monday(year, month, day):
    d = datetime(year, int(month), 7)
    offset = -d.weekday() #weekday = 0 means monday
    return d + timedelta(offset)
Answered By: Nick

A slightly different method – The date.weekday() function gives your an index of the day of the week (where Monday is 0 and Sunday is 6). You can use this value to directly calculate the which date any day of the week will fall on. For Mondays, something like this…

def first_monday(year, month):
    day = (8 - datetime.date(year, month, 1).weekday()) % 7
    return datetime.date(year, month, day)

Of course, you could make a generic version, that let you specify which day of the week you were after, like this:

def first_dow(year, month, dow):
    day = ((8 + dow) - datetime.date(year, month, 1).weekday()) % 7
    return datetime.date(year, month, day)

It accepts the same indexes as the date.weekday() function returns (Monday is 0, Sunday is 6). For example, to find the first Wednesday (2) of July 2022…

>>> first_dow(2022, 7, 2)
datetime.date(2022, 7, 6)
Answered By: Molomby

With numpy, calculating the first Monday of the month is much simpler that that.

import datetime
import numpy as np

any_date_in_month = datetime.datetime(year, month, day)

year_month = any_date_in_month.strftime('%Y-%m')
first_monday = np.busday_offset(year_month, 0, roll='forward', weekmask='Mon')

so just check anything you need against first_monday and you are set.

Answered By: norman123123