<p>我想很多人的答案都是在OP给出<code>fy</code>如何发挥作用的关键信息之前(edit:很多人都读过这个编辑,现在他们的答案也更新了)。OP需要<code>admission</code>到{<cd3>}之间的天数,该天数在财政年度内(1819年为2018年4月1日至2019年3月31日)。显然,每个人都知道,天数需要按日历月份划分。在</p>
<pre><code>from datetime import datetime, timedelta
# Function taken from https://stackoverflow.com/a/13565185/9462009
def lastDateOfThisMonth(any_day):
next_month = any_day.replace(day=28) + timedelta(days=4)
return next_month - timedelta(days=next_month.day)
def monthlyBeddays(admission, discharge, fy):
startFy = datetime.strptime('01-Apr-'+fy[:2], '%d-%b-%y')
endFy = datetime.strptime('01-Apr-'+fy[2:], '%d-%b-%y')
admissionDate = datetime.strptime(admission, '%d-%b-%Y')
dischargeDate = datetime.strptime(discharge, '%d-%b-%Y')
monthDates = {'Jan':0,'Feb':0,'Mar':0,'Apr':0,'May':0,'Jun':0,'Jul':0,'Aug':0,'Sep':0,'Oct':0,'Nov':0,'Dec':0}
# if admitted after end of fy or discharged before beginning of fy, zero days counted
if admissionDate > endFy or dischargeDate < startFy:
return monthDates
if admissionDate < startFy:
# Jump ahead to start at the first day of fy if admission was prior to the beginning of fy
now = startFy
else:
# If admission happened at or after the first day of fy, we begin counting from the admission date
now = admissionDate
while True:
month = datetime.strftime(now,'%b')
lastDateOfMonth = lastDateOfThisMonth(now)
if now >= endFy:
# If now is greater or equal to the first day of the next fy (endFy), we don't care about any of the following dates within the adm/dis date range
break
if month == datetime.strftime(dischargeDate,'%b') and datetime.strftime(now, '%Y') == datetime.strftime(dischargeDate, '%Y') and now >= startFy:
# If we reach the discharge month, we count this month and we're done
monthDates[month] = (dischargeDate - now).days # not adding one since in your example it seemed like you did not want to count the dischargeDate (Mar:4)
break
elif now < startFy:
# If now is less than the first day of this fy (startFy), we move on from this month to the next month until we reach this fy
pass
else:
# We are within this fy and have not reached the discharge month yet
monthDates[month] = (lastDateOfMonth - now).days + 1
month = datetime.strftime(now, '%b')
now = lastDateOfMonth + timedelta(days=1) # advance to the 1st of the next month
return monthDates
# Passes all six scenarios
# Scenario #1: admitted before fy, discharged before fy (didn't stay at all during fy)
print(monthlyBeddays("01-Jan-2018", "30-Mar-2018", '1819')) # {'Jan': 0, 'Feb': 0, 'Mar': 0, 'Apr': 0, 'May': 0, 'Jun': 0, 'Jul': 0, 'Aug': 0, 'Sep': 0, 'Oct': 0, 'Nov': 0, 'Dec': 0}
# Scenario #2: admitted before fy, discharged during fy
print(monthlyBeddays("01-Jan-2018", "30-May-2018", '1819')) # {'Jan': 0, 'Feb': 0, 'Mar': 0, 'Apr': 30, 'May': 29, 'Jun': 0, 'Jul': 0, 'Aug': 0, 'Sep': 0, 'Oct': 0, 'Nov': 0, 'Dec': 0}
# Scenario #3: admitted during fy, discharged during fy
print(monthlyBeddays("15-Apr-2018", "30-May-2018", '1819')) # {'Jan': 0, 'Feb': 0, 'Mar': 0, 'Apr': 16, 'May': 29, 'Jun': 0, 'Jul': 0, 'Aug': 0, 'Sep': 0, 'Oct': 0, 'Nov': 0, 'Dec': 0}
# Scenario #4: admitted during fy, discharged after fy
print(monthlyBeddays("15-Apr-2018", "30-May-2019", '1819')) # {'Jan': 31, 'Feb': 28, 'Mar': 31, 'Apr': 16, 'May': 31, 'Jun': 30, 'Jul': 31, 'Aug': 31, 'Sep': 30, 'Oct': 31, 'Nov': 30, 'Dec': 31}
# Scenario #5: admitted before fy, discharged after fy (stayed the whole fy)
print(monthlyBeddays("15-Mar-2018", "30-May-2019", '1819')) # {'Jan': 31, 'Feb': 28, 'Mar': 31, 'Apr': 30, 'May': 31, 'Jun': 30, 'Jul': 31, 'Aug': 31, 'Sep': 30, 'Oct': 31, 'Nov': 30, 'Dec': 31}
# Scenario #6: admitted after fy, discharged after fy (didn't stay at all during fy)
print(monthlyBeddays("15-Mar-2018", "30-May-2019", '1718')) # {'Jan': 0, 'Feb': 0, 'Mar': 17, 'Apr': 0, 'May': 0, 'Jun': 0, 'Jul': 0, 'Aug': 0, 'Sep': 0, 'Oct': 0, 'Nov': 0, 'Dec': 0}
</code></pre>