How can I convert from a datetime to a weekday of the month constant? - python-3.x

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...

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.

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

Related

Get dynamic dates for URL on any day of the month

I'm scraping a website with requests. The URL requires dynamic dates so i'm generating the dates to use with the following variables:
stmDt = (pd.to_datetime('today').date()+ pd.offsets.MonthBegin(-1)).strftime('%d-%b-%Y')
todDt = (pd.to_datetime('today').date()).strftime('%d-%b-%Y')
snmDt = (pd.to_datetime('today').date()+ pd.offsets.MonthBegin(1)).strftime('%d-%b-%Y')
enmDt = (pd.to_datetime('today').date()+ pd.offsets.MonthEnd(2)).strftime('%d-%b-%Y')
For this example, i'm running this script on 11/30/2022 (last day of the month).
stmDt = start this month date (first day of month on which we run script - 11/1/2022)
todDt = today (11/30/2022)
snmDt = start next month (12/1/2022)
enmDt = end next month (12/31/2022)
The date variables are correct most of the time, but it appears (for november run dates):
On the first day of the month: stmDt shows the first day of the
previous month (10/1/22)
On the last day of the month: enmDt shows the last day two months
from now (1/31/23)
How can I tweak these so they always give me the correct dates? Happy to use other packages to accomplish etc
Thanks
You can do this using dateutil.relativedelta like this:
from datetime import datetime
from dateutil.relativedelta import relativedelta
today = datetime.now()
stmDt = today.replace(day=1).strftime('%d-%b-%Y')
todDt = today.strftime('%d-%b-%Y')
snmDt = (today + relativedelta(months=1)).replace(day=1).strftime('%d-%b-%Y')
enmDt = ((today + relativedelta(months=2)).replace(day=1) - relativedelta(days=1)).strftime('%d-%b-%Y')

How to build a time series with Matplotlib

i have a database that contains all flights data for 2019. I want to plot a time series where the y-axis is the number of flights that are delayed ('DEP_DELAY_NEW')and x-axis is the day of the week.
The day of the week column is an integer, i.e. 1 is Monday, 2 is Tuesday etc.
`# only select delayed flights`
delayed_flights = df_airports_clean[df_airports_clean['ARR_DELAY_NEW'] >0]
delayed_flights['DAY_OF_WEEK'].value_counts()
1 44787
7 40678
2 33145
5 29629
4 27991
3 26499
6 24847
Name: DAY_OF_WEEK, dtype: int64
How do i convert the above into a time series? Additionally how do i change the integer for the 'day of week' into a string (i.e. 'Monday instead of '1'). i couldn't find the answer to those questions in this forum. Thank you
Let's break down the problem into two parts.
Converting the num_delayed columns into a time series
I am not sure what you meant by a time-series here. But the below code would work well for your plotting purpose.
delayed_flights = df_airports_clean[df_airports_clean['ARR_DELAY_NEW'] > 0]
delayed_series = delayed_flights['DAY_OF_WEEK'].value_counts()
delayed_df = pd.DataFrame(delayed_series, columns=['NUM_DELAYS'])
delayed_array = delayed_df['NUM_DELAYS'].values
delayed_array contains the array of delayed flight counts in order.
Converting the day in int into a weekday
You can easily do this by using the calendar module.
>>> import calendar
>>> calendar.day_name[0]
'Monday'
If Monday is not the first day of week, you can use setfirstweekday to change it.
In your case, your day integers are 1-indexed and hence you would need to subtract 1 to make it 0-indexed. Another easy workaround would be to define a dictionary with keys as day_int and values as weekday.

What is the purpose of offset in conjunction with datetime in Python 3.x?

I'm new to python and I'm looking to work with datetime. I have some files generated every Sunday and I like to move the furthest Sunday out of the current folder eg: 2020-04-12, 2020-04-19, 2020-04-26.
I have found some examples on getting a specific date from today's date and I was able to modify it a tab bit. Eg. I can go back and get last week's Sunday with a specific date:
from datetime import date
from datetime import timedelta
import datetime
today = datetime.datetime(2020,4,13)
offset = (today.weekday() + 1) % 7
sunday = today - timedelta(days=offset)
#print (offset)
print(sunday)
I am confused by the offset variable. What is (today.weekday() + 1) % 7 doing? I have read the Python doc and not quite wrapping my head around it. With +1, I get the date 2020-04-12, which is a Sunday, great. When I do -1 (the other thing is if I set it to (today.weekday() - 1) % 7), I get 2020-04-07, a Tuesday. How did it jump from Sunday the 12th to Tuesday the 7th?
Additionally, how do I get it to jump back 3 weeks? that's where I'm also stuck.
Alright, so if today's Wednesday, then today.weekday() is 2, because it starts counting from 0 on Monday. Not sure why, but that's life.
So (2 + 1) % 7) = 3. That means that 3 days ago was Sunday. Hence your code:
offset = (today.weekday() + 1) % 7 # How many days ago was sunday
sunday = today - timedelta(days=offset) # Go backwards from today that many days
You'll notice that if you subtract one instead of add one, that means we're going backwards (because we're sutracting the timedelta object) by two fewer days than before (because 2 - 1 is equivalent to (2 + 1) - 2, that is, two fewer days). If you started by going backwards enough days to get to Sunday, and now you're going backwards two fewer days, you'll end up on Tuesday, which is two days later than Sunday.
The easiest way to shift which week you're headed to is to set the weeks argument in timedelta:
n_weeks = 3
sunday = today - timedelta(days=offset, weeks=n_weeks)
that's equivalent to, but much prettier than:
sunday = today - timedelta(days=offset + n_weeks * 7)

total number of days from current date if we want to know like after 2 weeks, 3 months , 1 year

I want to know the total number of days from current date.
if given date is 2 Feb 2018. and i want to calculate number of days after 2 weeks/3 months/1 year. keeping in mind of leap year or not.
Language - python3
Is there any library in python which give me this.
The dateutil module has a way to do this very conveniently. Sample code:
import datetime
import dateutil
today = datetime.date.today()
delta = dateutil.relativedelta.relativedelta(years=1, months=3, weeks=2)
desired_date = today + delta
desired_date
Output:
datetime.date(2019, 5, 16)

Python date range based on current date

I'm looking to achieve a search of files based on user input on a date. For example, I'm attempting to write the script to ask user for a range in which to search (month to date, last full week, or specific day).
last full week needs to go backward, to the last full week - so if today is Wednesday, the script should go back to the previous (2)Sunday(s) as a start range to the Saturday that just past, while also accounting for what day it is currently:
Sun(start)---Mon---Tue---Wed---Thu---Fri---Sat(end)---Sun---Mon---Tue---Wed (today)
Howevver, it needs to also account for what day it is in relation to the above, meaning that regardless of what "today" is, the search criteria is always one full week behind (if its Sunday, it just goes to last sunday to 'yesterday, Saturday')
From some examples attempting similar things I've seen here and here, I've attempted to join, modify, and add over the last couple of days:
import datetime
import os
import dateutil.relativedelta
import timedelta
class AuditFileCheck():
"""File Compliance Checker."""
def datechoice(self):
"""Select date."""
print("Checking the Audit Files for compliance.")
print("Today is", datetime.date.today().strftime(" %A."))
print("\nI will check either for file compliances."
"\nSearch criteria is either by MONTH to date, last full WEEK, "
"or individual DAY: [M/W/D]")
print(now.strftime('Week of %Y%m%d'))
weekbefore = now - timedelta(days=6)
print(
"Week of {weekbefore:%A, %m-%d-%Y} to {now:%A, %m-%d-%Y}").format(**vars())
input_search = input(
"Enter search range: Month to date, Prior Week, or by day [M/W/D]")
def search_month(d, w, m, weekday, month):
"""Establish search from month start, or prior month if today is first of current month."""
if input_search.lower() == "m":
current_month = datetime(today.month, 1, today.year)
if current_month == datetime.today():
current_month == dateutil.relativedelta.relativedelta(
months=-1)
return m - datetime.timedelta(current_month)
m = current_month()
print(current_month)
# TODO ensure the prior month is used if 'today' is before the end of
# first full week in current month
if input_search.lower() == "w":
prior_week = weekday + d.weekday()
if prior_week >= 0: # Target day already happened this week
prior_week -= 6
return d - datetime.timedelta(prior_week)
d = datetime.date.today()
# 6 = Sunday, 0 = Monday, 1 = Tuesday...
previous_monday = previous_weekday(d, 6)
print(previous_monday)
# TODO search files
if input_search.lower() == "d":
day_search = input(
"Enter a specific date within to search [YYYYMMDD]")
return d
print("Searching through...")
# TODO search files from set_day
This bit:
previous_sunday = previous_weekday(d, 8)
adjusting the integer adjusts how far back it looks.
I'm having some trouble with getting this to function properly. What am I doing wrong here? The more I attempt to play with it, the more confused I become and less it works...

Resources