How to get week number between two months? - python

I am running sql query in python, I have a requirement to dynamically generate dates and append it to my sql query.This script runs on every Monday. If the week of Monday falls between two months then I have to restrict the date range till last of the previous month (i.e 30th or 31st). Any Ideas on how to achieve this ?
I tried to get the weeknumber and their respective dates but I couldn't find the exact function which will return me list of dates with corresponding week number

You can use the following code to get the week number between two months:
import datetime
def get_weeks_between_dates(start_date, end_date):
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
week_number = (end_date - start_date).days / 7
return week_number
start_date = '2017-01-01'
end_date = '2017-02-01'
print(get_weeks_between_dates(start_date, end_date))

Find the possibly truncated week starting at a given date and not extending beyond the end of the month.
If what you mean is "the seven days starting with the day the script is run", you could use the following:
from datetime import date, timedelta, datetime as dt
from typing import Tuple
def one_week_from(base: None | date = None) -> Tuple[date, date]:
'''Returns a tuple consisting of the given starting date (default today)
and the end of the week starting at that date, or the last day of the
month, whichever comes first. (That is, a week truncated at the end of
the month.)
'''
if base is None:
base = dt.now().date()
if base.month < 12:
next_first = date(base.year, base.month + 1, 1)
else:
next_first = date(base.year + 1, 1, 1))
return (base, min(base + timedelta(6), next_first - timedelta(1)))
If necessary, you could use a function like this to find a Monday:
# Same imports as above
def monday_not_later_than(base: None | date = None) -> date:
'''Returns the last Monday no later than the given date (default: today).
(That is, the given date if it is a Monday; otherwise the previous
Monday.)
'''
if base is None:
base = dt.now().date()
return base - timedelta(base.weekday())
Get the ISO week number
If you have a datetime.date or datetime.datetime object, you can use the isocalendar() member function to get a tuple consisting of the year, week_number and iso_day_of_week for that date. (Use datetime.datetime.now() to get the current day, but watch out for time zone artefacts.)
The ISO week always starts with a Monday; it is counted in the year which contains the Wednesday of the week. The ISO weekday is from 1 to 7 (Monday == 1), unlike the datetime.date.weekday which ranges from 0 to 6 (Monday == 0).

Related

Python: Finding Start/End Date Based on Duration, Work Week Length, and One Date

I'm currently trying to fill in some bad data.
Sometimes there is a Start Date and no End Date and sometimes there is an End Date and no Start Date, but the table gives the Duration (in days) of the task and the Work Week Length.
(Note: Work Week Length is 5 day (excludes weekends), 6 day (excludes Sunday), and 7 day.)
Example of the Table
How would I go about this?
I've calculated unknown Durations already with Start/End Dates and Work Week Length, but am unsure how to go about doing things a little backwards.
You can use the timedelta function of the datetime module to help you.
You can calculate the number of days by working out the full weeks (7 per week) + any additional days worked after accounting for the weeks.
Here is an example:
import datetime
# sample data
start_date = "07/01/2022"
duration = 6
work_week = 5
# calculate the days to add (full weeks + left over days)
days = (7 * (duration // work_week)) + (duration % work_week)
# add the days to the start date
end_date = datetime.datetime.strptime(start_date, "%d/%m/%Y") + datetime.timedelta(days=days)
# display the result
print(end_date)
If you have an end date and wish to find the start date then the code is similar to the above except you subtract the number of days from the end date:
# subtract the days from the end date
start_date = datetime.datetime.strptime(end_date, "%d/%m/%Y") - datetime.timedelta(days=days)
You can adapt the above examples to work with your database. It may be useful to create a suitable function that you can call as shown below:
def calculate_date(date, duration, work_week, is_end_date=False):
# calculate the weeks
weeks = (7 * (duration // work_week))
# calculate remaining work days
remaining_days = (duration % work_week)
# calculate total actual days
days = weeks + remaining_days
# determine date
current = datetime.datetime.strptime(start_date, "%d/%m/%Y")
if is_end_date:
result = current - datetime.timedelta(days=days)
else:
result = current + datetime.timedelta(days=days)
return result

How to increment date (month and year) and set the day to default based on specific conditions?

My Date should always fall on 8th or 22nd that comes off the input date.
For Example:
If the input date is 20190415 then the output date should be 20190422 as that's the nearest date and if input date is 20190424 then the output date should be 20190508.
Example1:
input_date = 20190415
Expected output_date = 20190422
Example2:
input_date = 20190424
Expected output_date = 20190508
Example3:
input_date = 20190506
Expected output_date = 20190508
Example4:
input_date = 20191223
Expected output_date = 20200108
How do we achieve this using Python?
You can check if the day is greater than 22, and if so you set it to the 8th of the next month. If it's between 8 and 22 you set it to 22 of the same month and if it's below the 8th you set it to the 8th of the month. There's probably more elegant ways to do it using date math, but this will work for your scenario.
Use the datetime module to find out what the "next month" is. One way to do it is to add a timedelta of 1 month to the first of the current month, and then change the date on that datetime object to the 8th. Here's a quick example of how that might look like:
from datetime import date, timedelta
input_date = date(2019, 12, 23)
if input_date.day > 22:
output_date = date(input_date.year, input_date.month) + timedelta(days=31)
output_date = output_date.replace(day = 8)
You can read a lot more about the details of how the datetime module works on the official documentation. It's kind of a long read, but I actually have that page bookmarked because I always have to go back and reference how to actually use the module :)
Considering the input as string, next date can be calculated using timedelta, check out the below code:
if 8<datetime.strptime(input_date, "%Y%m%d").day < 22:
delta = 22 - datetime.strptime(input_date, "%Y%m%d").day
print((datetime.strptime(input_date, "%Y%m%d") +
timedelta(days=delta)).strftime("%Y%m%d"))
elif datetime.strptime(str(input_date), "%Y%m%d").day < 8:
delta = 8 - datetime.strptime(input_date, "%Y%m%d").day
print((datetime.strptime(input_date, "%Y%m%d") +
timedelta(days=delta)).strftime("%Y%m%d"))
else:
delta = (datetime.strptime(input_date, "%Y%m%d")+ relativedelta(months=+1)).day -8
print((datetime.strptime(input_date, "%Y%m%d") + relativedelta(months=+1) -
timedelta(days=delta)).strftime("%Y%m%d") )

Calendar week list of the current month in Python

I am trying to get the weeks of the current month. I can get the number of the week in that month(current_w) but I will need to get a list in the correct order. For example, for July, it will be w = [27, 28, 29, 30] because current week is in the third order of the 4 weeks of this month. Can somebody help me on that?
import datetime
kw = datetime.datetime.today().isocalendar()[1]
weeks = [7,14,21,28]
for idx, i in enumerate(weeks):
delta = datetime.timedelta(days=i)
if (a - delta).month != a.month:
current_w = idx
You could use datetime to get both the first and the last week and then just everything in between.
import datetime
import calendar
year = datetime.datetime.now().year
month = datetime.datetime.now().month
first_week = datetime.datetime(year, month, calendar.monthrange(year, month)[0]).isocalendar()[1]
last_week = datetime.datetime(year, month, calendar.monthrange(year, month)[1]).isocalendar()[1]
print(list(range(first_week, last_week + 1)))
from datetime import datetime would save you all the datetime.datetime usage btw.
If you only want weeks that are fully included in a month, the first week will be the one that contains the 7th of that month. And the last week will one before the one that contains the 1st of next month.
That is enough to give the following function:
def weeks_in_month(month, year=None):
"""Returns the (ISO) weeks fully contained in a month.
month is an integer between 1 and 12. Year is the current year
if not given"""
if year is None:
year = datetime.date.today().year
first = datetime.date(year, month, 7).isocalendar()[1]
nextd = datetime.date(year + 1, 1, 1) if month == 12 \
else datetime.date(year, month + 1, 1)
nextw = nextd.isocalendar()[1]
return list(range(first, nextw))

Get start and end date of quarter from date and fiscal year end

Given a certain data, I would like to know the easiest/cleanest way of getting the beginning and the end of the previous quarter.
For example, given the following date:
from datetime import datetime
example_date = datetime.strptime('2017-05-12', '%Y-%m-%d')
if the fiscal year ends in September (month=9), the result should be:
datetime.datetime(2017,01,01), datetime.datetime(2017,03,31)
On the other end, if the fiscal year ended in October (month=10) the result would be
datetime.datetime(2017,02,01), datetime.datetime(2017,04,30)
The prototype of the function would be something like this:
def get_range(date_in, fy_end_month):
pass
You can define two function: one for the getting the quarter of a given date, and another for getting the start and end dates of a given quarter. To get the start and end dates of the previous quarter, you would just need to subtract one from the current quarter (with some handling of first quarter).
import datetime as dt
from dateutil import parser
from dateutil.relativedelta import relativedelta
def get_quarter(date):
"""
Returns the calendar quarter of `date`
"""
return 1+(date.month-1)//3
def quarter_start_end(quarter, year=None):
"""
Returns datetime.daet object for the start
and end dates of `quarter` for the input `year`
If `year` is none, it defaults to the current
year.
"""
if year is None:
year = dt.datetime.now().year
d = dt.date(year, 1+3*(quarter-1), 1)
return d, d+relativedelta(months=3, days=-1)
Once these are defined, we can define a simple function to get the previous quarter.
def prev_quarter_range(date):
"""
Returns the start and end dates of the previous quarter
before `date`.
"""
if isinstance(date, str):
date = parser.parse(date)
year = date.year
q = get_quarter(date)-1
# logic to handle the first quarter case
if q==0:
q = 4
year -= 1
return quarter_start_end(q, year)
And now you can assign the returned dates to variables
prev_q_start, prev_q_end = prev_quarter_range('2-feb-2011')
print(prev_q_start)
print(prev_q_end)
# prints:
2010-10-01
2010-12-31

get dates of present month in a list and difference in dates

How do I go about printing these:
At any given time, I should be able to return the dates of the present month in a list.
eg. Since this is March, I want to print a list [20140301, ...,20140331].
Find the difference in number of days from current date and the first of that month.
e.g. today is 4th March. I should be able to print the difference as 3
Thanks in advance
Here is what you can do in Python 2.7.3
from datetime import date
import calendar
today = date.today()
first_of_month = today.replace(day=1)
_, number_of_days_in_month = calendar.monthrange(first_of_month.year, first_of_month.month)
for i in range(1, number_of_days_in_month+1):
newdate = today.replace(day = i)
print newdate #prints all dates in months
#Lets calculate difference between 14th of this month and 1st
randomdate = today.replace(day=14)
delta = randomdate - first_of_month
print delta.days

Categories