Omeed Totakhel Omeed Totakhel - 1 month ago 11
Python Question

A simple mathematic Operation python

I have a method which returns the number of days within a specified range and excluding some specific days like Friday. here is an example if you take out friday and thursday, from 2016-8-6 to 2016-9-6 the result will be 8 days holiday and 24 working day. in case i want to do the reverse operation how do i find the end date (2016-9-6) if i have only working days and start date.

from datetime import datetime, timedelta

def measure_workingdays(start_date, end_date, off_days):
format = "%Y-%m-%d"
if not isinstance(start_date, datetime):
start_date = datetime.strptime(start_date, format)
if not isinstance(end_date, datetime):
end_date = datetime.strptime(end_date, format)
total_days = (end_date - start_date).days + 1 # + 1 Because it count one day less
holiday = 0
start = start_date
for rec in range(total_days):
day = start.strftime("%a")
if day in off_days:
holiday += 1
start += timedelta(days=1)
print(holiday) # 8
working_days = total_days - holiday
print(working_days) # 24


start_date = "2016-8-6"
start_date = datetime.strptime(start_date, "%Y-%m-%d")
end_date = "2016-9-6"
end_date = datetime.strptime(end_date, "%Y-%m-%d")
off_day = ['Fri','Thu']

working_days = measure_weekdays(start_date, end_date, off_day)


Example of Reverse operation

def measure_weekdays_reverse(start_date, paid, off_days):
format = "%Y-%m-%d"
if not isinstance(start_date, datetime):
start_date = datetime.strptime(start_date, format)
holiday = 0
start = start_date
for rec in range(paid):
day = start.strftime("%a")
if day in off_days:
holiday += 1
start += timedelta(days=1)
print(holiday) # Output 6 instead of 8
last_paid_date = start + timedelta(days=holiday)
print(last_paid_date) # output 2016-09-05 insteaad of 2016-09-06

total_days = measure_weekdays_reverse(start_date, 24, ["Fri","Thu"])

Answer

The error is that you only loop a fix number of times (the number of paid days), so if you encounter holidays, you will in fact not iterate enough to find all the true paid days, which may still hide some holidays.

You can fix this by adding an inner loop on the holidays. Change this:

for rec in range(paid):
    day = start.strftime("%a")
    if day in off_days:
        holiday += 1
    start += timedelta(days=1)
print(holiday) # Output 6 instead of 8
last_paid_date = start + timedelta(days=holiday)

to this:

for rec in range(paid):
    day = start.strftime("%a")
    while day in off_days:
        holiday += 1
        start += timedelta(days=1)
        day = start.strftime("%a")
    last_paid_date = start
    start += timedelta(days=1)
print(holiday)