Skip to content

Instantly share code, notes, and snippets.

@Markcanfly
Last active June 7, 2022 22:22
Show Gist options
  • Save Markcanfly/670824e41c683f455a4e9602ef583819 to your computer and use it in GitHub Desktop.
Save Markcanfly/670824e41c683f455a4e9602ef583819 to your computer and use it in GitHub Desktop.
Covered Time by Intervals
def covered_time(begin: datetime, end: datetime, ranges: List[List[datetime,datetime]]) -> timedelta:
"""Calculate the covered timespan of a range by other ranges
Takes a base range defined by begin, end,
and several other ranges, and calculates the amount of time covered
within the base range by the other ranges (overlap time)
Args:
begin: base range begin datetime
end: base range end datetime
range: [begin, end] lists of covering timestamps
Returns:
overlap: timedelta
"""
if (len(ranges) == 0):
return timedelta(0)
# Cut down each time to the base range
for span in ranges:
begin_delta = begin - span[0]
span[0] = span[0] + begin_delta if begin_delta > timedelta(0) else span[0]
end_delta = span[1] - end
span[1] = span[1] - end_delta if end_delta > timedelta(0) else span[1]
times = []
for begin, end in ranges:
times.append({'type': 'begin', 'time': begin})
times.append({'type': 'end', 'time': end})
# Count covered time using a state machine
covered = timedelta(0) # Covered time in base range
previous_begin = times[0]
depth = 0
for time in times:
if time['type'] == 'begin':
depth += 1
elif time['type'] == 'end':
depth -= 1
if depth == 1: # Entered first nested covered interval
previous_begin = time['time']
elif depth == 0: # Exited last nested covered interval
covered += time['time'] - previous_begin
return covered
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment