Search code examples
python-2.7ubuntuodoo-10odoo-accounting

How to get the number of Days in a Specific Month between Two Dates in Python


I have two date fields campaign_start_date and campaign_end_date. I want to count the number of days in each month that comes in-between the campaign_start_date and campaign_end_date.

eg:

campaign_start_date  = September 7 2017
campaign_end_date    = November 6 2017

The solution should be :

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

How can I achieve this using Python? So far I have achieved:

@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

Solution

  • Calculate the duration in days:

    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 
    

    Some hints for further calculations:

    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
    

    This way you can calculate the number of days in each month of the campaign (keep in mind to check if campaign_end_date is in another month than campaign_start_date

    For calculations you can also access the fields of a date, e.g.

    campaign_start_date.day
    campaign_start_date.month
    campaign_start_date.year
    

    To calculate the number of involved month in your campaign and to get a list of the month to calculate the duration per month you can use this (based on the answer of m.antkowicz in Python: get all months in range?). It's important to set the day to 1 (current = current.replace(day=1)) before and inside the loop, otherwise you skip a month when your startdate is 31st of a month and the next month is shorter than 31 days or if you have a longer period:

    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)
    

    which prints (when you use current.strftime('%Y-%m-%d'):

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

    now you can loop over the result list and calculate the number of days per months:

    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
    

    which gives you the desired "No:of days in Month x" as a list:

    [24, 31, 6]