Measuring months between two dates : legislative definition of months - python

I'm looking to build code that represents the definition of months in a piece of Australian legislation - the Interpretations Act (1987).
Please note that I am still a relative novice to Python.
The legal definition
The definition reads as follows:
(1) In any Act, month means a period:
(a) starting at the start of any day of one of the calendar months; and.
(b) ending: (i) immediately before the start of the corresponding day of the next calendar month; or.
(ii) if there is no such day--at the end of the next calendar month.
I've been advised that this definition means that if the start of a month begins on 16/07/2019, for the purposes of a) for example, the relevant month does not conclude until 11:59:59:etc:pm on 15/08/2019 - or functionally, 16/08/2019.
For the purpose of b), then, the "end of a month" is defined at similarly 11:59:59:etc:pm on the relevant final day of the month. So if you have two dates - 31/08/2019 and 30/09/2019 - the relevant month does not conclude until 11:59:59:etc:pm on 30/09/2019 - or functionally, 01/10/2019.
I need to output the difference between two dates in months in order to reflect that the legislation I'm coding asks for a difference between two dates specifically in months.
I'm looking to do this with either datetime or datetime64 objects if possible, to avoid converting between variables unnecessarily.
What I've tried so far.
I've used the below code to find the difference between two dates in months, using relativedelta:
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-15', '%Y-%m-%d')
date2 = datetime.strptime('2020-02-05', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
print(r)
My expected output for this is 5 months, as there are five complete months and then a fraction of a month that isn't completed by date2. This returns the expected result, and replicates the functionality of a) in the legislation.
However, when I try to replicate b) with the below code:
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-31', '%Y-%m-%d')
date2 = datetime.strptime('2019-11-30', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
print(r)
This returns the result of 4 months. Because 2019-11-30 is not the end of the relevant calendar month, this is incorrect - I should be getting a result of 3 months for this code, as the month is not completed until 11:59:59:etc.
Expected results
Below are four test cases that I've used to test the results of this code.
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-25', '%Y-%m-%d')
date2 = datetime.strptime('2019-09-10', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 0
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-25', '%Y-%m-%d')
date2 = datetime.strptime('2019-09-25', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 1
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-31', '%Y-%m-%d')
date2 = datetime.strptime('2019-11-30', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 3
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-31', '%Y-%m-%d')
date2 = datetime.strptime('2019-12-01', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 4
EDIT: I've written the inputs for the second two test cases, and after reviewing Alain T.'s response, have revised to the below.
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-01', '%Y-%m-%d')
date2 = datetime.strptime('2019-11-30', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 3
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-01', '%Y-%m-%d')
date2 = datetime.strptime('2019-12-01', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 4
from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2019-08-31', '%Y-%m-%d')
date2 = datetime.strptime('2019-12-01', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)
r.months = 3

This can be calculated without converting to date types except for the edge case where dates are the last day of the month (where they actually correspond to day zero of the next month).
from datetime import date
def isLastDay(y,m,d):
return date.fromordinal(date(y,m,d).toordinal()+1).month != m
def legalMonthDif(date1,date2):
y1,m1,d1 = map(int,date1.split("-"))
y2,m2,d2 = map(int,date2.split("-"))
if isLastDay(y1,m1,d1): m1,d1 = m1+1,0
if isLastDay(y2,m2,d2): m2,d2 = m2+1,0
return y2*12+m2 -y1*12-m1 -(d2<d1)
output:
legalMonthDif('2019-08-15','2020-02-05') #5
legalMonthDif('2019-08-31','2019-11-30') #3
legalMonthDif('2019-08-25','2019-09-10') #0
legalMonthDif('2019-08-25','2019-09-25') #1
legalMonthDif('2019-08-31','2019-11-30') #3
legalMonthDif('2019-08-01','2019-12-01') #4
legalMonthDif('2019-08-31','2019-12-01') #3
legalMonthDif('2019-08-15','2019-12-01') #3
You could also do it completely without the datetime library by implementing a daysOfMonth function to compute the number of days in any month:
def daysOfMonth(y,m):
return 30+(m+m//8)%2-(m==2)*(2-(y%4==0 and not y%100==0 or y%400==0))
def legalMonthDif(date1,date2):
y1,m1,d1 = map(int,date1.split("-"))
y2,m2,d2 = map(int,date2.split("-"))
if daysOfMonth(y1,m1) == d1: m1,d1 = m1+1,0
if daysOfMonth(y2,m2) == d2: m2,d2 = m2+1,0
return y2*12+m2 -y1*12-m1 -(d2<d1)

dates = [('2019-07-16','2019-08-15'),('2019-08-31','2019-09-30'),
('2019-08-15','2020-02-05'),('2019-08-31','2019-11-30'),
('2019-08-25','2019-09-10'),('2019-08-25','2019-09-25'),
('2019-08-31','2019-12-01'),('2019-08-15' , '2019-12-01'),
('2019-08-01', '2019-11-30'),('2019-08-01', '2019-12-01')]
Using Pandas date-time functionality. This relies on the fact that adding months to a timestamp will truncate to the end of the month if the resulting date doesn't exist - providing a means to test for the (b)(ii) part of the spec.
import pandas as pd
def f(a,b):
earlier,later = sorted((a,b))
rel_months = later.month - earlier.month
delta_months = rel_months + (later.year - earlier.year) * 12
period_end = earlier + pd.DateOffset(months=delta_months)
# sentinals for implementing logic of (b)(ii) of the definition
period_end_isEOM = period_end + pd.tseries.offsets.MonthEnd(0)
later_isEOM = later == later + pd.tseries.offsets.MonthEnd(0)
next_month = period_end + pd.tseries.offsets.MonthBegin(0)
# begin with the delta - period_end == later - then adjust
months = delta_months
# this is straightforward
if period_end > later:
months -= 1
# did period_end get truncated to the end of a month
if period_end_isEOM and (period_end.day < earlier.day):
# actual end of period would be beginning of next month
if later < next_month: # probably also means later_isEOM or later == period_end
months -= 1
return months
for a,b in dates:
a, b = map(pd.Timestamp, (a,b))
c = f(a,b)
print(f'{a.date()} - {b.date()} --> {c}')
>>>
2019-07-16 - 2019-08-15 --> 0
2019-08-31 - 2019-09-30 --> 0
2019-08-15 - 2020-02-05 --> 5
2019-08-31 - 2019-11-30 --> 2
2019-08-25 - 2019-09-10 --> 0
2019-08-25 - 2019-09-25 --> 1
2019-08-31 - 2019-12-01 --> 3
2019-08-15 - 2019-12-01 --> 3
2019-08-01 - 2019-11-30 --> 3
2019-08-01 - 2019-12-01 --> 4
>>>
pd.TimeStamp is an instance of datetime.datetime
This appears to work - only the OP can judge - but I can't help thinking that there is some builtin functionality I'm still not utilizing. Should be able to subclass pandas.DateOffset and customize it to make the calcs easier.
Solutions using a subclass of Pandas.DateOffset.
from pandas import DateOffset, Timestamp
from pandas.tseries.offsets import MonthBegin
class LegislativeMonth(DateOffset):
def __init__(self, n=1, normalize=False, months=1):
# restricted to months
kwds = {'months':months}
super().__init__(n=1, normalize=False, **kwds)
def apply(self,other):
end_date = super().apply(other)
if end_date.day < other.day:
# truncated to month end
end_date = end_date + MonthBegin(1)
return end_date
for a,b in dates:
earlier,later = sorted(map(Timestamp, (a,b)))
delta_months = later.month - earlier.month
delta_months += (later.year - earlier.year) * 12
end_of_period = earlier + LegislativeMonth(months=delta_months)
if end_of_period > later:
delta_months -= 1
print(f'{earlier.date()} - {later.date()} --> {delta_months}')
# another
one_month = LegislativeMonth(months=1)
for a,b in dates:
earlier,later = sorted(map(Timestamp, (a,b)))
end_period = earlier
months = 0
while later >= end_period + one_month:
months += 1
end_period += one_month
print(f'{earlier.date()} - {later.date()} --> {months}')
Finally it looks like relativedelta will do what you want if you ensure that it is called with the earlier date as the first item - (earlier,later)
from datetime import datetime
from dateutil.relativedelta import relativedelta
for a,b in dates:
## earlier,later = sorted(map(Timestamp, (a,b)))
earlier,later = sorted((datetime.strptime(a, '%Y-%m-%d'),
datetime.strptime(b, '%Y-%m-%d')))
rd = relativedelta(earlier,later)
print(f'{earlier.date()} - {later.date()} --> {abs(rd.months)}')
Using the dates at the top of this post all print the following:
2019-07-16 - 2019-08-15 --> 0
2019-08-31 - 2019-09-30 --> 0
2019-08-15 - 2020-02-05 --> 5
2019-08-31 - 2019-11-30 --> 2
2019-08-25 - 2019-09-10 --> 0
2019-08-25 - 2019-09-25 --> 1
2019-08-31 - 2019-12-01 --> 3
2019-08-15 - 2019-12-01 --> 3
2019-08-01 - 2019-11-30 --> 3
2019-08-01 - 2019-12-01 --> 4

I ended up writing the below functions which capture the intended functionality of this legislation:
def find_corresponding_date(start_date):
day = start_date.day
month = start_date.month
year = start_date.year
next_month = month + 1
next_year = year
if month == 12:
next_month = 1
next_year = year + 1
try:
new_date = py_datetime(year=next_year, month=next_month, day=day)
except ValueError:
next_month = next_month + 1
if next_month == 13:
next_month = 1
next_year = next_year + 1
new_date = py_datetime(year=next_year, month=next_month, day=1)
return new_date
else:
return new_date
def toPyDateTime(numpyDate):
return py_datetime.strptime(str(numpyDate), "%Y-%m-%d")
def count_months(sdate, edate):
start_date = toPyDateTime(sdate)
end_date = toPyDateTime(edate)
count = 0
corres_date = start_date
while(True):
corres_date = find_corresponding_date(corres_date)
if(corres_date > end_date):
return count
break
else:
count = count + 1

Related

How Can we Loop Through a Range of Rolling Dates?

I did some Googling and figured out how to generate all Friday dates in a year.
# get all Fridays in a year
from datetime import date, timedelta
def allfridays(year):
d = date(year, 1, 1) # January 1st
d += timedelta(days = 8 - 2) # Friday
while d.year == year:
yield d
d += timedelta(days = 7)
for d in allfridays(2022):
print(d)
Result:
2022-01-07
2022-01-14
2022-01-21
etc.
2022-12-16
2022-12-23
2022-12-30
Now, I'm trying to figure out how to loop through a range of rolling dates, so like 2022-01-07 + 60 days, then 2022-01-14 + 60 days, then 2022-01-21 + 60 days.
step #1:
start = '2022-01-07'
end = '2022-03-08'
step #2:
start = '2022-01-14'
end = '2022-03-15'
Ideally, I want to pass in the start and end date loop, into another loop, which looks like this...
price_data = []
for ticker in tickers:
try:
prices = wb.DataReader(ticker, start = start.strftime('%m/%d/%Y'), end = end.strftime('%m/%d/%Y'), data_source='yahoo')[['Adj Close']]
price_data.append(prices.assign(ticker=ticker)[['ticker', 'Adj Close']])
except:
print(ticker)
df = pd.concat(price_data)
as you use pandas then you can try to do it this way:
import pandas as pd
year = 2022
dates = pd.date_range(start=f'{year}-01-01',end=f'{year}-12-31',freq='W-FRI')
df = pd.DataFrame({'my_dates':dates, 'sixty_ahead':dates + pd.Timedelta(days=60)})
print(df.head())
'''
my_dates sixty_ahead
0 2022-01-07 2022-03-08
1 2022-01-14 2022-03-15
2 2022-01-21 2022-03-22
3 2022-01-28 2022-03-29
4 2022-02-04 2022-04-05
First, we have to figure out how to get the first Friday of a given year. Next, we will calculate the start, end days.
import datetime
FRIDAY = 4 # Based on Monday=0
WEEK = datetime.timedelta(days=7)
def first_friday(year):
"""Return the first Friday of the year."""
the_date = datetime.date(year, 1, 1)
while the_date.weekday() != FRIDAY:
the_date = the_date + datetime.timedelta(days=1)
return the_date
def friday_ranges(year, days_count):
"""
Generate date ranges that starts on first Friday of `year` and
lasts for `days_count`.
"""
DURATION = datetime.timedelta(days=days_count)
start_date = first_friday(year)
end_date = start_date + DURATION
while end_date.year == year:
yield start_date, end_date
start_date += WEEK
end_date = start_date + DURATION
for start_date, end_date in friday_ranges(year=2022, days_count=60):
# Do what you want with start_date and end_date
print((start_date, end_date))
Sample output:
(datetime.date(2022, 1, 7), datetime.date(2022, 3, 8))
(datetime.date(2022, 1, 14), datetime.date(2022, 3, 15))
(datetime.date(2022, 1, 21), datetime.date(2022, 3, 22))
...
(datetime.date(2022, 10, 21), datetime.date(2022, 12, 20))
(datetime.date(2022, 10, 28), datetime.date(2022, 12, 27))
Notes
The algorithm for first Friday is simple: Start with Jan 1, then keep advancing the day until Friday
I made an assumption that the end date must fall into the specified year. If that is not the case, you can adjust the condition in the while loop
This could work maybe. You can add the condition, the end of the loop within the lambda function.
from datetime import date, timedelta
def allfridays(year):
d = date(year, 1, 1) # January 1st
d += timedelta(days = 8 - 2) # Friday
while d.year == year:
yield d
d += timedelta(days = 7)
list_dates = []
for d in allfridays(2022):
list_dates.append(d)
add_days = map(lambda x: x+timedelta(days = 60),list_dates)
print(list(add_days))
Oh my, I totally missed this before. The solution below works just fine.
import pandas as pd
# get all Fridays in a year
from datetime import date, timedelta
def allfridays(year):
d = date(year, 1, 1) # January 1st
d += timedelta(days = 8 - 2) # Friday
while d.year == year:
yield d
d += timedelta(days = 7)
lst=[]
for d in allfridays(2022):
lst.append(d)
df = pd.DataFrame(lst)
print(type(df))
df.columns = ['my_dates']
df['sixty_ahead'] = df['my_dates'] + timedelta(days=60)
df
Result:
my_dates sixty_ahead
0 2022-01-07 2022-03-08
1 2022-01-14 2022-03-15
2 2022-01-21 2022-03-22
etc.
49 2022-12-16 2023-02-14
50 2022-12-23 2023-02-21
51 2022-12-30 2023-02-28

Get fourth to the last month?

I'm trying to find out fourth to the last month with a snippet.
Considering, september, fourth to the last month would be june.
I tried to get the required month and year like this
from datetime import date, datetime, timedelta
current_date = datetime.now()
last_4th_month = current_date.month - 3
year = current_date.year
if current_date.month == 3:
last_4th_month = 12
year = current_date.year - 1
if current_date.month == 2:
last_4th_month = 11
year = current_date.year - 1
if current_date.month == 1:
last_4th_month = 10
year = current_date.year - 1
print(last_4th_month, year)
Is there any efficient and better way to do this?
TYPO IN THE QUESTION:
Get fourth to the last month in python
Try this:
from datetime import date
from dateutil.relativedelta import relativedelta
four_months = date.today() + relativedelta(months=-3)
print(four_months.strftime("%B, %Y"))
Output: June, 2021
If 3rd party libraries can be used, dateutil's relativedelta module offers a simple solution:
from datetime import datetime
from dateutil.relativedelta import relativedelta
current_date = datetime.now()
target_date = current_date - relativedelta(months=3)
print(target_date.month, target_date.year)
Outputs 6 2021
You can compute the last_4th_month with the standard library:
from datetime import date
today = date.today()
month = today.month - 3 if today.month - 3 > 0 else 12 - today.month
year = today.year if today.month > month else today.year - 1
last_4th_month = date(year, month, today.day)
# today = date(2021, 9, 6)
>>> last_4th_month.strftime('%B, %Y')
'June, 2021'
# today = date(2021, 2, 18)
>>> last_4th_month.strftime('%B, %Y')
'October, 2020'

Don't take leap years into account when adding months to date in Pandas

I need to do the following. I have a date column in my data frame and I need to add x months to it like this:
df = pd.DataFrame({'date':['2019-01-01', '2018-01-01']})
df['date'] = pd.to_datetime(df['date']).dt.date
months = 24
df['date'] = df['date'] + np.timedelta64(months, 'M')
The problem is I don't want to take leap years into account so I have '2021-01-01' as the result of the first date instead of '2020-12-31'. (2020 was a leap year.) The other date is fine.
Is there a simple solution to this? I haven't found any so far.
Thank you.
import pandas as pd
import datetime
import numpy as np
df = pd.DataFrame({'date':['2019-01-01', '2018-01-01']})
df['date'] = pd.to_datetime(df['date'])
months=24
if df['date'].dt.is_leap_year.any() == False:
df['date'] = df['date'] + np.timedelta64(months, 'M')
else:
df['date'] = df['date'] + np.timedelta64(months, 'M') - np.timedelta64(df['date'].dt.is_leap_year.sum(), 'D')
df['date'] = df['date'] + pd.offsets.DateOffset(years=2)
similar to: How to add a year to a column of dates in pandas
Restrict yourself to adding only months smaller than 12. Leap year is a concept of "years". A function like np.timedelta() on months can never get it; it's by design.
import pandas as pd
import numpy as np
from datetime import datetime
def add_date(date):
d = date + np.timedelta64(months, 'M')
y = d.year
if d.is_leap_year:
y = y + 1 # Here you can add more conditions
return datetime(year=y, month=1, day=1)
#or return d + pd.offsets.DateOffset(years=1)
return datetime(year=y, month=d.month, day=d.day) #or d
df = pd.DataFrame({'date':['2019-01-03', '2018-01-01','2018-11-21','2017-05-01']})
months = 24
df['date'] = pd.to_datetime(df['date']).apply(add_date)
print(df)
# Or you can use by dayofyear attribute provide by pandas
def add_date(date):
d = date + np.timedelta64(months, 'M')
days = 0
if d.is_leap_year:
days = 367 - d.day_of_year
return date + np.timedelta64(months, 'M') + np.timedelta64(days, 'D')
Output
date
0 2021-01-02 #d = 2021-01-02 11:38:24 - Not leap year
1 2021-01-01 #d = 2020-01-01 11:38:24 - Leap year
2 2021-01-01 #d = 2020-11-20 11:38:24 - Leap year
3 2019-05-01 #d = 2019-05-01 11:38:24 - Not leap year
# where d=date+ np.timedelta64(24, 'M')
If you wish to check the date in dataframe, you can do following,
def add_date(date):
days = 0
if date.is_leap_year :
days = 367 - date.day_of_year
return date + np.timedelta64(months, 'M') + np.timedelta64(days, 'D')

Finding dates between two dates

Say I want to find all Mondays between two dates, date_A and date_B
from datetime import date, timedelta
days_to_substract = 50
date_A = date.today()-timedelta(days=days_to_subtract)
date_B = date.today()
How can I do this? Is there any way to iterate between dates?
you can iterate over date range with generator:
def date_range(date1,date2):
while date1 < date2:
yield date1
date1 = date1 + timedelta(days=1)
and iterate it like this:
for dat in date_range(date_A,date_B):
<your code here>
Find last Monday from current date and find remaining based on 7 days difference:
from datetime import date, timedelta
days_to_substract = 50
date_A = date.today()-timedelta(days=days_to_substract)
date_B = date.today()
cDay = date_B - timedelta(days=date_B.weekday())
print cDay
while cDay > date_A:
cDay = cDay - timedelta(days=7)
print cDay
Output:
2014-03-24
2014-03-17
2014-03-10
2014-03-03
2014-02-24
2014-02-17
2014-02-10
2014-02-03
Maybe this :
from datetime import date, timedelta
days_to_substract = 50
date_A = date.today()-timedelta(days=days_to_substract)
date_B = date.today()
date_tmp = date_A
numOfMondays = 0
deltaStep = 1
while date_tmp < date_B:
if date_tmp.strftime("%A") != "Monday":
print("Date before first monday {}".format(date_tmp))
date_tmp += timedelta(days=1)
else:
print("Monday : {}".format(date_tmp))
date_tmp += timedelta(days=7)
numOfMondays += 1
print("from {} to {} there are {} monday".format(date_A, date_B, numOfMondays))
with output
Date before first monday 2014-02-05
Date before first monday 2014-02-06
Date before first monday 2014-02-07
Date before first monday 2014-02-08
Date before first monday 2014-02-09
Monday : 2014-02-10
Monday : 2014-02-17
Monday : 2014-02-24
Monday : 2014-03-03
Monday : 2014-03-10
Monday : 2014-03-17
Monday : 2014-03-24
from 2014-02-04 to 2014-03-26 there are 7 monday
Do you mean something like this?
def day_iter(start, end):
step = timedelta(days=1)
for i in range((end - start).days):
yield start + i*step
end = date.today()
start = end - timedelta(days=50)
for day in day_iter(start, end):
day.weekday() == 0:
print day.strftime("%A %Y-%m-%d")
Output:
Monday 2014-02-10
Monday 2014-02-17
Monday 2014-02-24
Monday 2014-03-03
Monday 2014-03-10
Monday 2014-03-17
Monday 2014-03-24
You could also do something like this:
today = date.today()
past = today - timedelta(50)
if past.weekday() != 0:
monday = past + timedelta(7 - past.weekday())
else:
monday = past
one_week = timedelta(7)
while monday < today:
print monday
monday += one_week
which outputs:
2014-02-10
2014-02-17
2014-02-24
2014-03-03
2014-03-10
2014-03-17
2014-03-24
And you can generalize this into a function like this:
def past_weekdays(depth, weekday):
today = date.today()
past = today - timedelta(depth)
if past.weekday() != weekday:
past_day = past + timedelta((7 + (weekday - past.weekday())) % 7)
else:
past_day = past
one_week = timedelta(7)
while past_day < today:
yield past_day
past_day += one_week

Finding the date of the next Saturday

How would one go about finding the date of the next Saturday in Python? Preferably using datetime and in the format '2013-05-25'?
>>> from datetime import datetime, timedelta
>>> d = datetime.strptime('2013-05-27', '%Y-%m-%d') # Monday
>>> t = timedelta((12 - d.weekday()) % 7)
>>> d + t
datetime.datetime(2013, 6, 1, 0, 0)
>>> (d + t).strftime('%Y-%m-%d')
'2013-06-01'
I use (12 - d.weekday()) % 7 to compute the delta in days between given day and next Saturday because weekday is between 0 (Monday) and 6 (Sunday), so Saturday is 5. But:
5 and 12 are the same modulo 7 (yes, we have 7 days in a week :-) )
so 12 - d.weekday() is between 6 and 12 where 5 - d.weekday() would be between 5 and -1
so this allows me not to handle the negative case (-1 for Sunday).
Here is a very simple version (no check) for any weekday:
>>> def get_next_weekday(startdate, weekday):
"""
#startdate: given date, in format '2013-05-25'
#weekday: week day as a integer, between 0 (Monday) to 6 (Sunday)
"""
d = datetime.strptime(startdate, '%Y-%m-%d')
t = timedelta((7 + weekday - d.weekday()) % 7)
return (d + t).strftime('%Y-%m-%d')
>>> get_next_weekday('2013-05-27', 5) # 5 = Saturday
'2013-06-01'
I found this pendulum pretty useful. Just one line
In [4]: pendulum.now().next(pendulum.SATURDAY).strftime('%Y-%m-%d')
Out[4]: '2019-04-27'
See below for more details:
In [1]: import pendulum
In [2]: pendulum.now()
Out[2]: DateTime(2019, 4, 24, 17, 28, 13, 776007, tzinfo=Timezone('America/Los_Angeles'))
In [3]: pendulum.now().next(pendulum.SATURDAY)
Out[3]: DateTime(2019, 4, 27, 0, 0, 0, tzinfo=Timezone('America/Los_Angeles'))
In [4]: pendulum.now().next(pendulum.SATURDAY).strftime('%Y-%m-%d')
Out[4]: '2019-04-27'
You need two main packages,
import datetime
import calendar
Once you have those, you can simply get the desired date for the week by the following code,
today = datetime.date.today() #reference point.
saturday = today + datetime.timedelta((calendar.SATURDAY-today.weekday()) % 7 )
saturday
Bonus
Following the content, if you type
saturday.weekday()
It will result 5.
Therefore, you can also use 5 in place of calendar.SATURDAY and you will get same result.
saturday = today + datetime.timedelta((5-today.weekday()) % 7 )
if you just want the date from today (inspired from Emanuelle )
def get_next_weekday(weekday_number):
"""
#weekday: week day as a integer, between 0 (Monday) to 6 (Sunday)
"""
assert 0 <= weekday_number <= 6
today_date = datetime.today()
next_week_day = timedelta((7 + weekday_number - today_date.weekday()) % 7)
return (today_date + next_week_day).strftime('%d/%m/%Y')
Again, based on Emmanuel's example, but making 0-6 conform to your week:
ScheduleShift = -1 # make Saturday end of week
EndofWeekDay = lambda do : do + datetime.timedelta( ( ScheduleShift + (13 - do.weekday() ) %7 ) )
Which can be called with:
EndofWeekDay( datetime.date.today() )
returning a datetime.date object
Just wanted to share a code. With this, you will get a list of dates when Saturday days will be in the next 10 days.
from datetime import datetime, timedelta
target_day = 'Saturday'
now_ = datetime.today().date()
how_many_days = 10
next_date = [now_ + timedelta(days=x) for x in range(how_many_days) if (now_ + timedelta(days=x)).strftime("%A") == target_day]
print(next_date)

Categories