简体   繁体   中英

Get number of days in a specific month that are in a date range

Haven't been able to find an answer to this problem. Basically what I'm trying to do is this:

Take a daterange, for example October 10th to November 25th. What is the best algorithm for determining how many of the days in the daterange are in October and how many are in November.

Something like this:

def daysInMonthFromDaterange(daterange, month):
    # do stuff
    return days

I know that this is pretty easy to implement, I'm just wondering if there's a very good or efficient algorithm.

Thanks

Borrowing the algorithm from this answer How do I divide a date range into months in Python? , this might work. The inputs are in date format, but can be changed to date strings if preferred:

import datetime
begin = '2018-10-10'
end = '2018-11-25'

dt_start = datetime.datetime.strptime(begin, '%Y-%m-%d')
dt_end = datetime.datetime.strptime(end, '%Y-%m-%d')
one_day = datetime.timedelta(1)
start_dates = [dt_start]
end_dates = []
today = dt_start
while today <= dt_end:
    #print(today)
    tomorrow = today + one_day
    if tomorrow.month != today.month:
        start_dates.append(tomorrow)
        end_dates.append(today)
    today = tomorrow

end_dates.append(dt_end)

out_fmt = '%d %B %Y'
for start, end in zip(start_dates,end_dates):
    diff = (end - start).days
    print('{} to {}: {} days'.format(start.strftime(out_fmt), end.strftime(out_fmt), diff))

result:

10 October 2018 to 31 October 2018: 21 days
01 November 2018 to 25 November 2018: 24 days

The problem as stated may not have a unique answer. For example what should you get from daysInMonthFromDaterange('Feb 15 - Mar 15', 'February') ? That will depend on the year!

But if you substitute actual days, I would suggest converting from dates to integer days, using the first of the month to the first of the next month as your definition of a month. This is now reduced to intersecting intervals of integers, which is much easier.

The assumption that the first of the month always happened deals with months of different lengths, variable length months, and even correctly handles the traditional placement of the switch from the Julian calendar to the Gregorian. See cal 1752 for that. (It will not handle that switch for all locations though. Should you be dealing with a library that does Romanian dates in 1919, you could have a problem...)

You can use the datetime module:

from datetime import datetime

start = datetime(2018,10,10)
end = datetime(2018,11,25)
print((end - start).days)

Something like this would work:

def daysInMonthFromDaterange(date1, date2, month):
    return [x for x in range(date1.toordinal(), date2.toordinal()) if datetime.date.fromordinal(x).year == month.year and datetime.date.fromordinal(x).month == month.month]

print(len(days_in_month(date(2018,10,10), date(2018,11,25), date(2018,10,01))))

This just loops through all the days between date1 and date2, and returns it as part of a list if it matches the year and month of the third argument.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM