Как получить количество дней в конкретном месяце между двумя датами в Python

У меня есть два поля даты campaign_start_date а также campaign_end_date, Я хочу посчитать количество дней в каждом месяце, которое проходит между campaign_start_date а также campaign_end_date,

например:

campaign_start_date  = September 7 2017
campaign_end_date    = November 6 2017

Решение должно быть:

Total No:of days       = 61 days
No: of months          = 3 months
Month 1                = 9/7/2017 to 9/30/2017
Month 2                = 10/1/2017 to 10/31/2017
Month 3                = 11/1/2017 to 11/6/2017
No:of days in Month 1  = 24 days
No:of days in Month 2  = 31 days
No:of days in Month 3  = 6 days

Как я могу добиться этого с помощью Python? До сих пор я достиг:

@api.multi
    def print_date(self):
        start_date = datetime.strptime(self.start_date, "%Y-%m-%d %H:%M:%S")
        end_date = datetime.strptime(self.end_date, "%Y-%m-%d %H:%M:%S")
        campaign_start_date = date(start_date.year,start_date.month,start_date.day)
        campaign_end_date = date(end_date.year,end_date.month,end_date.day)
        duration = (campaign_end_date-campaign_start_date).days  
        return True

1 ответ

Решение

Рассчитать продолжительность в днях:

from datetime import date

campaign_start_date = date(2017, 9, 7)
campaign_end_date = date(2017, 10, 6)
duration = (campaign_end_date-campaign_start_date).days
print campaign_start_date, campaign_end_date, duration 

Некоторые подсказки для дальнейших расчетов:

import calendar

campaign_end_month_start = campaign_end_date.replace(day=1)
days_in_month_campaign_end = (campaign_end_date - campaign_end_month_start).days + 1

range_startmonth = calendar.monthrange(campaign_start_date.year, campaign_start_date.month)
campaign_start_month_ends = campaign_start_date.replace(day=range_startmonth[1])

days_in_month_campaign_begins = (campaign_start_month_ends - campaign_start_date).days

Таким образом, вы можете рассчитать количество дней в каждом месяце кампании (не забудьте проверить, campaign_end_date в другой месяц, чем campaign_start_date

Для расчетов вы также можете получить доступ к полям даты, например,

campaign_start_date.day
campaign_start_date.month
campaign_start_date.year

Чтобы рассчитать количество вовлеченных месяцев в вашей кампании и получить список месяцев, чтобы рассчитать продолжительность месяца, вы можете использовать это (основываясь на ответе m.antkowicz в Python: получить все месяцы в диапазоне?). Важно установить день на 1 (current = current.replace(day=1)) до и внутри цикла, в противном случае вы пропускаете месяц, когда ваша начальная дата 31 числа месяца, а следующий месяц короче 31 дня или если у вас более длительный период:

from datetime import date, datetime, timedelta    
current = campaign_start_date
result = [current]

current = current.replace(day=1)
while current <= campaign_end_date:
    current += timedelta(days=32)
    current = current.replace(day=1)
    result.append(datetime(current.year, current.month, 1))

print result, len(result)

какие отпечатки (когда вы используете current.strftime('%Y-%m-%d'):

['2017-09-07', '2017-10-01', '2017-11-01'] 3

Теперь вы можете перебрать список результатов и рассчитать количество дней в месяцах:

durations= []
for curr in result:
    curr_range = calendar.monthrange(curr.year, curr.month)
    curr_duration = (curr_range[1] - curr.day)+1
    if (curr.month < campaign_end_date.month):
        durations.append(curr_duration)
    else:
        durations.append(campaign_end_date.day)

print durations

который дает вам желаемое "Нет: дней в месяце х" в виде списка:

[24, 31, 6]

Это надежное решение, которое заботится о финиках разных лет.

def get_months_and_durations(start_date,end_date):
    current = start_date
    result = [current]

    current = current.replace(day=1)
    while current <= end_date:
        current += timedelta(days=32)
        current = current.replace(day=1)
        result.append(datetime(current.year, current.month, 1).date())

    durations= []
    for curr in result[:-1]:
        curr_range = calendar.monthrange(curr.year, curr.month)
        curr_duration = (curr_range[1] - curr.day)+1

        if ((curr.month == end_date.month) & (curr.year == end_date.year)):
            durations.append(end_date.day)
        else:
            durations.append(curr_duration)
    return result[:-1],durations
Другие вопросы по тегам