Efficient date range overlap calculation in python?

后端 未结 7 1166
南旧
南旧 2020-11-28 02:50

I have two date ranges where each range is determined by a start and end date (obviously, datetime.date() instances). The two ranges can overlap or not. I need the number of

相关标签:
7条回答
  • 2020-11-28 03:14

    You can use the datetimerange package: https://pypi.org/project/DateTimeRange/

    from datetimerange import DateTimeRange
    time_range1 = DateTimeRange("2015-01-01T00:00:00+0900", "2015-01-04T00:20:00+0900") 
    time_range2 = DateTimeRange("2015-01-01T00:00:10+0900", "2015-01-04T00:20:00+0900")
    tem3 = time_range1.intersection(time_range2)
    if tem3.NOT_A_TIME_STR == 'NaT':  # No overlap
        S_Time = 0
    else: # Output the overlap seconds
        S_Time = tem3.timedelta.total_seconds()
    

    "2015-01-01T00:00:00+0900" inside the DateTimeRange() can also be datetime format, like Timestamp('2017-08-30 20:36:25').

    0 讨论(0)
  • 2020-11-28 03:18

    Ok my solution is a bit wonky because my df uses all series - but lets say you have the following columns, 2 of which are fixed which is your "Fiscal Year". PoP is "Period of performance" which is your variable data:

    df['PoP_Start']
    df['PoP_End']
    df['FY19_Start'] = '10/1/2018'
    df['FY19_End'] = '09/30/2019'
    

    Assume all of the data is in datetime format ie -

    df['FY19_Start'] = pd.to_datetime(df['FY19_Start'])
    df['FY19_End'] = pd.to_datetime(df['FY19_End'])
    

    Try the following equations to find the number of days overlap:

    min1 = np.minimum(df['POP_End'], df['FY19_End'])
    max2 = np.maximum(df['POP_Start'], df['FY19_Start'])
    
    df['Overlap_2019'] = (min1 - max2) / np.timedelta64(1, 'D')
    df['Overlap_2019'] = np.maximum(df['Overlap_2019']+1,0)
    
    0 讨论(0)
  • Function calls are more expensive than arithmetic operations.

    The fastest way of doing this involves 2 subtractions and 1 min():

    min(r1.end - r2.start, r2.end - r1.start).days + 1
    

    compared with the next best which needs 1 subtraction, 1 min() and a max():

    (min(r1.end, r2.end) - max(r1.start, r2.start)).days + 1
    

    Of course with both expressions you still need to check for a positive overlap.

    0 讨论(0)
  • 2020-11-28 03:27
    • Determine the latest of the two start dates and the earliest of the two end dates.
    • Compute the timedelta by subtracting them.
    • If the delta is positive, that is the number of days of overlap.

    Here is an example calculation:

    >>> from datetime import datetime
    >>> from collections import namedtuple
    >>> Range = namedtuple('Range', ['start', 'end'])
    
    >>> r1 = Range(start=datetime(2012, 1, 15), end=datetime(2012, 5, 10))
    >>> r2 = Range(start=datetime(2012, 3, 20), end=datetime(2012, 9, 15))
    >>> latest_start = max(r1.start, r2.start)
    >>> earliest_end = min(r1.end, r2.end)
    >>> delta = (earliest_end - latest_start).days + 1
    >>> overlap = max(0, delta)
    >>> overlap
    52
    
    0 讨论(0)
  • 2020-11-28 03:27

    Pseudocode:

     1 + max( -1, min( a.dateEnd, b.dateEnd) - max( a.dateStart, b.dateStart) )
    
    0 讨论(0)
  • 2020-11-28 03:36
    def get_overlap(r1,r2):
        latest_start=max(r1[0],r2[0])
        earliest_end=min(r1[1],r2[1])
        delta=(earliest_end-latest_start).days
        if delta>0:
            return delta+1
        else:
            return 0
    
    0 讨论(0)
提交回复
热议问题