How can I convert from a datetime to a weekday of the month constant?

299 Views Asked by At

What I want to do is figure out what X of the month this is, and returning the relative delta constant for it (Su Mo Tu...). I have found many examples of jumping to a specific day of the month (1). For instance today is the 3rd Tuesday of December and I can get to it by doing this: + relativedelta(month=12, day=1, weekday=TU(3))) but what I want to do is the opposite: Put in today's date and subtract the first of the month and get something like TU(3) or if it were the 4th wednesday to get: WE(4)

My ultimate goal is to then be able to transfer this constant to a different month or timedelta object and find the equivalent 3rd Tuesday, or 4th Wednesday, etc...

2

There are 2 best solutions below

1
On

This is a solution that I have come up with, maybe you'll find it less complicated.

It also seems to be about 4 times faster, which if you process a lot of dates can make a difference.

from datetime import *
from dateutil.relativedelta import *

def weekDayOfTheMonth(xdate):
   daylist = [MO,TU,WE,TH,FR,SA,SU]
   weekday = xdate.weekday()
   firstDayOfTheMonth = datetime(xdate.year, xdate.month, 1)
   interval = (weekday + 7 - firstDayOfTheMonth.weekday() ) % 7
   firstOfThisWeekDay = datetime(xdate.year, xdate.month, 1 + interval)
   n = ((xdate.day - firstOfThisWeekDay.day) / 7) + 1
   return daylist[weekday](n)

print(weekDayOfTheMonth(datetime.today()))
print(weekDayOfTheMonth(datetime(2018,11,24)))

Basically what happens is that:

I find what day of the week is the first day of given month.
Based on that information I can easily calculate first day of any given weekday in given month.
Then I can even more easily calculate that for example 18th of December 2018 is third Tuesday of this month.

0
On

Ok I found a way using rrule to create a list of days in the month that share the current weekday up until today, then length of this list becomes the Nth. Than I use a list as a lookup table for the weekday constants. Not tested to see if this will work for every day of the month but this is a start.

from datetime import *; from dateutil.relativedelta import *
from dateutil.rrule import rrule, WEEKLY
import calendar

def dayofthemonth(xdate):
    daylist = [MO,TU,WE,TH,FR,SA,SU]

    thisweekday = daylist[xdate.weekday()]

    thisdaylist = list(rrule(freq=WEEKLY, dtstart=xdate+relativedelta(day=1), until=xdate, byweekday=xdate.weekday()))

    return thisweekday(len(thisdaylist))

print(dayofthemonth(datetime.today())) #correctly returns TU(+3) for 2018, 12, 18