Get dynamic dates for URL on any day of the month - python-3.x

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')

Related

Get difference between two week days that are in string

Problem Statement:
Am developing a custom job scheduler that needs to be run on given days. It takes start date and end date as string and third param is list of week days on which job should run.
Start day can be different with given days but first job should run on next valid day
Let suppose Start date is 2022-09-07 (so day name is Wednesday) but given frequency days are ["Monday", "Friday", "Saturday"] so i need to run my first job on coming Friday and for this i need to calculate difference between start date and first valid day (in this case it's Friday)
So how can i do this python to run my first job on valid day (that can be in any position of given frequency days list) and also after one job complete i need to also get next valid day. I did some work but unfortunately its not working. Here is what i did
sorted_week_days_list = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
start_date = "2022-09-07"
valid_frequency_days = ["Monday", "Tuesday", "Friday"] # It can be any days in sorted order
start_date_object = datetime.datetime.strptime(start_date, "%Y-%m-%d")
given_start_day = start_date_object.strftime("%A")
if given_start_day not in valid_frequency_days:
# Need help to implement logic to get date for valid day
You should use the datetime.weekday() method to pull out the day of the week for days of interest. Assuming that you have dates similar to the format you show above, it is easy to convert, and also just use the day index for your "allowable start days" (Monday=0).
Then you can jig up a little function to look for the next start date in your sorted list and figure out how many days you need to wait.
Example below does that and also "rolls over" the weekend as needed.
Code:
from datetime import datetime, timedelta
from bisect import bisect_left
start_date = "2022-09-09"
valid_start_dates = [1, 4] # It can be any days in sorted order
start_date_object = datetime.strptime(start_date, "%Y-%m-%d")
d=start_date_object.weekday()
print(f'the numbered day of the week is: {d}')
def days_till_start(day, valid_start_days):
idx = bisect_left(valid_start_days, day)
if idx >= len(valid_start_days): # wrap around to next start
return valid_start_days[0] + 7 - day
elif day == valid_start_days[idx]:
return 0
else:
return valid_start_days[idx] - day
print(days_till_start(d, valid_start_dates))
start_dates = ['2022-09-05', '2022-09-06', '2022-09-07', '2022-09-08', '2022-09-09', '2022-09-10']
start_wkdys = [datetime.strptime(d, "%Y-%m-%d").weekday() for d in start_dates]
for d in start_wkdys:
print(f'day index is: {d}')
print(f'next start date is {days_till_start(d, valid_start_dates)} away')
print()
Output:
the numbered day of the week is: 4
0
day index is: 0
next start date is 1 away
day index is: 1
next start date is 0 away
day index is: 2
next start date is 2 away
day index is: 3
next start date is 1 away
day index is: 4
next start date is 0 away
day index is: 5
next start date is 3 away

Function returning the following days and months in python3

I am writing a webscraper and the URL is based on the dates:
checkin_month=2&checkin_monthday=21&checkin_year=2020&checkout_month=2&checkout_monthday=22
There are 4 variables: checkin day and month, and checkout day and month. Checkout day will be always be = checkin day + 1. But when the newmonth is ending, checkout day is 1 and checkout month = checkin month +1.
Is there any function or library I can use to somehow implement it or do I have to write my own code to solve this?
You can use:
from datetime import timedelta
then :
yourDate += timedelta(days=1)
This previous code increments your date by one day. But, to increment the date, your date must be of type datetime.
Below, the documentation of thhis class.
class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
You can see a tutorial to manipulate date here : https://www.dataquest.io/blog/python-datetime-tutorial/

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

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

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

ValueError: day is out of range for month python

I am writing code that lets users write down dates and times for things they have on. It takes in the date on which it starts, the start time and finish time. It also allows the user to specify if they want it to carry over into multiple weeks (every Monday for a month for example)
I am using a for loop to do this, and because of the different months having different days I obviously want (if the next Monday for example is in the next month) it to have the correct date.
This is my code:
for i in range(0 , times):
day = day
month = month
fulldateadd = datetime.date(year, month, day)
day = day + 7
if month == ( '01' or '03' or '05' or '07' or '10'or '12'):
if day > 31:
print(day)
day = day - 31
print(day)
month = month + 1
elif month == ( '04' or '06'or '09' or '11'):
if day > 30:
print(day)
day = day - 30
print(day)
month = month + 1
elif month == '02':
if day > 29:
print(day)
day = day - 29
print(day)
month = month + 1
When running this and testing to see if it goes correctly into the new month I get the error:
File "C:\Users\dansi\AppData\Local\Programs\Python\Python36-32\gui test 3.py", line 73, in addtimeslot
fulldateadd = datetime.date(year, month, day)
ValueError: day is out of range for month
Where have I gone wrong?
It's hard to be completely accurate without seeing some of the previous code (for example, where do day, month, year, and times come from?), but here's how you might be able to use timedelta in your code:
fulldateadd = datetime.date(year, month, day)
for i in range(times):
fulldateadd = fulldateadd + datetime.timedelta(7)
A timedelta instance represents a period of time, rather than a specific absolute time. By default, a single integer passed to the constructor represents a number of days. So timedelta(7) gives you an object that represents 7 days.
timedelta instances can then be used with datetime or date instances using basic arithmetic. For example, date(2016, 12, 31) + timedelta(1) would give you date(2017, 1, 1) without you needing to do anything special.

Resources