Django date filter - find a date in-between - python-3.x

I'm attempting to create a query that returns an event if it runs at any point in a given period of time between 2 dates.
model:
class MyModel(models.Model):
start_date = models.DateField(auto_now=False, blank=True, null=True, verbose_name="Start date")
hd_end_date = models.DateField(blank=True, default=None, null=True, verbose_name="End date")
Current code to try and filter:
import calendar
max_day = calendar.monthrange(year, month)[1]
start = "{}-{}-01".format(year, month)
end = "{}-{}-{}".format(year, month, max_day)
# If the event starts in the month, or if it ends in the month
filter.append(Q(start_date__range=[start, end]) |
Q(hd_end_date__range=[start, end]))
My models have a start_date and an end_date (hd_end_date). This logic appeared to work as intended at first. However there is problem and I know what is, just not how to solve it.
For example if my event model starts in December and finishes in February the above code would return an event for December and in February but it wouldn't return one for January as it neither starts or ends in that month. How can I adjust this code so that it would return an event that run over multiple months.

Appears I was over thinking it, and resolved the issue by simplifying.
filter.append(Q(start_date__month__lte=month, hd_end_date__month__gte=month))
I realised that I could just look at the month and didn't need to range the dates, as all I wanted to know is that the event ran on that month between it's start and end date.

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

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/

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

How do I get the Month End Personal Time Off Days used?

Using the Start Date and End Date of PTO - Personal Time Off Days Used only count days used up to end of prior month, excluding weekends and U.S Holidays in that certain month. Example of a Holiday is Sept 7th 2015 in the United States.
My goals are:
Create a Data Item Month End Personal Time Off Days used.
Of course it should be getting the number of PTO Days USED from the prior month only.
Exclude weekends in that certain month. So if the Resource takes a Leave on Friday and Monday, Saturday and Sunday should not be excluded in the computation.
How to exclude U.S Holidays, if this is possible that's great but if it's not possible then I'm okay with numbers 1, 2 and 3.
I have created a Data Item column that captures the PTO days used. But this is good for Year to date.
Case when [PTO Info].[PTO Audit].[PTOAuditTypeId] = 31571
and [PTO Info].[PTO Audit].[TimeOffTypeId] = 31566
then [PTO Info].[PTO Audit].[PTODays]
when [PTO Info].[PTO Audit].[PTOAuditTypeId]=31572
and [PTO Info].[PTO Audit].[TimeOffTypeId] = 31566
and [PTO Info].[PTO Audit].[PTODays] < 0
then abs([PTO Info].[PTO Audit].[PTODays] )
else 0 end
I'm not sure if the query below can help.
A calendar table is really going to help you out here. Assuming it has one record per calendar date, you can use this table to note weekends, holidays, fiscal periods vs Calendar periods, beginning of month/end of month dates. A number of things that can help simplify your date based queries.
See this question here for an example on creating a calendar table.
The main point is to create a data set with 1 record per date, with information about each date including Month, Day of Week, Holiday status, etc.
Without a calendar table, you can use database functions to generate your set of dates on the fly.
Getting the Month number for a date can be done with
extract([Month], <date field goes here> )
Getting a list of values from nothing will be required to generate your list of dates (if you don't have a calendar table with 1 record per date to use) will vary depending on your source database. In oracle I use a 'select from all_objects' type query to achieve this.
An example from Ask Tom:
select to_date(:start_date,'dd-mon-yyyy') + rownum -1
from all_objects
where rownum <=
to_date(:end_date,'dd-mon-yyyy')-to_date(:start_date,'dd-mon-yyyy')+1
For Sql Server refer to this stackoverflow question here.
Once you have a data set with your calendar type information, you can join it to your query above:
join mycalendar cal on cal.date >= c.PTOStartDate
and cal.date <= c.PTOEndDate
Also note, _add_days is a Cognos function. When building your source queries, try and use Native functions, like in oracle you can 'c.PTOStartDate + a.PTODays'. Mixing Cognos functions with native functions will sometime force parts of your queries to be processed locally on the Cognos server. Generally speaking, the more work that happens on the database, the faster your reports will run.
Once you have joined to the calendar data, you are going to have your records multiplied out so that you have 1 record per date. (You would not want to be doing any summary math on PTODays here, as it will be inflated.)
Now you can add clauses to track your rules.
where cal.Day_Of_Week between 2 and 6
and cal.Is_Holiday = 'N'
Now if you are pulling a specific month, you can add that to the criteria:
and cal.CalendarPeriod = '201508'
Or if you are covering a longer period, but wanting to report a summary per month, you can group by month.
Final query could look something like this:
select c.UserID, cal.CalendarPeriod, count(*) PTO_Days
from dbo.PTOCalendar c
join myCalendar cal on on cal.date >= c.PTOStartDate
and cal.date <= c.PTOEndDate
where cal.day_of_week between 2 and 6
and cal.Is_Holiday = 'N'
group by c.UserID, cal.CalendarPeriod
So if employee with UserID 1234 Took a 7 day vacation from thursday June 25th to Friday July 3th, that covered 9 days, the result you get here will be:
1234 201506 4
1234 201507 3
You can join these results to your final query above to track days off per month.

Using Workday when start date is a wekeend date

I have a spreadhseet that pulls Planned Maintenace due dates. I am calculating 5 potential days the work can be scheduled, from 2 days before to days days after, so a range of 5 days. Unfortunately, sometimes the original due date is a weekend date(our business system calculates but doesn't append for weekend dates). So when I calculate the first 2 days, =workdate(A1,-2,holiday) and =workdate(A1,-1,holiday)it works fine, however for the 3rd date =workdate(A1,0,holiday) returns the original due date even if it's a weekend date.
Example, July 6th 2013 is a Saturday, so
1. workdate(A1,-2,holiday) = 7/3/2013
2. workdate(A1,-1,holiday) = 7/5/2013
3. workdate(A1,0,holiday) = 7/6/2013 needs to be 7/8/2013
4. workdate(A1,1,holiday) = 7/8/2013 needs to be 7/9/2013
5. workdate(A1,2,holiday) = 7/9/2013 needs to be 7/10/2013
Is there any way to compensate for a start date that is a weekend date!
Thanks in advance for any help or suggestions.
The function it appears you are using is workday(), not workdate()? So what you probably need to do is put an adjustment on the # you pass to Workday if the day of the week is Sat/Sun.
=WORKDAY(A1,IF(OR(TEXT(A1,"ddd") = "Sat",TEXT(A1,"ddd") = "Sun"),1,0))
=WORKDAY(A1,IF(OR(TEXT(A1,"ddd") = "Sat",TEXT(A1,"ddd") = "Sun"),2,1))
=WORKDAY(A1,IF(OR(TEXT(A1,"ddd") = "Sat",TEXT(A1,"ddd") = "Sun"),3,2))

Resources