Библиотека python-ranges
, которую я написал некоторое время, go может быть полезна для этого:
from ranges import Range, RangeSet
from datetime import datetime, timedelta
from functools import reduce
# times, transcribed from above
# and converted to datetimes (so that we can use timedelta math)
times = [
(datetime(1, 1, 1, 12, 25), timedelta(hours=1)), # (12:25, 1:00),
(datetime(1, 1, 1, 13, 35), timedelta(minutes=15)), # (13:35, 0:15),
(datetime(1, 1, 1, 14, 3), timedelta(minutes=20)), # (14:03, 0:20),
(datetime(1, 1, 1, 15, 40), timedelta(minutes=10)), # (15:40, 0:10),
(datetime(1, 1, 1, 16, 15), timedelta(minutes=65)), # (16:15, 1:05),
(datetime(1, 1, 1, 17, 30), timedelta(minutes=40)), # (17:30, 0:40),
]
# make a RangeSet that encompasses the entire day
wholeDay = RangeSet(Range(datetime(1, 1, 1, 12, 00), datetime(1, 1, 1, 20, 00)))
# remove our times from the whole day
wholeDay -= [Range(start, start + duration) for (start, duration) in times]
# get a list of correspondences with timedeltas
bins = {}
for h in range(12, 20):
# create the 1-hour-long range
period = Range(datetime(1, 1, 1, h), datetime(1, 1, 1, h + 1))
# compute number of minutes in this range *were consumed* during the whole day
# which is the same as the number of minutes in this period that are not contained in wholeDay
# (in other words, the length of the set difference)
# We have to do this roundabout counting-second method,
# because timedelta() doesn't work with sum() natively
time_seconds = sum(rng.length().seconds for rng in period.difference(wholeDay))
# finally, add to dict
bins[period] = timedelta(seconds=time_seconds)
Это приводит к следующему bins
:
{Range[datetime.datetime(1, 1, 1, 12, 0), datetime.datetime(1, 1, 1, 13, 0)): datetime.timedelta(seconds=2100),
Range[datetime.datetime(1, 1, 1, 13, 0), datetime.datetime(1, 1, 1, 14, 0)): datetime.timedelta(seconds=2400),
Range[datetime.datetime(1, 1, 1, 14, 0), datetime.datetime(1, 1, 1, 15, 0)): datetime.timedelta(seconds=1200),
Range[datetime.datetime(1, 1, 1, 15, 0), datetime.datetime(1, 1, 1, 16, 0)): datetime.timedelta(seconds=600),
Range[datetime.datetime(1, 1, 1, 16, 0), datetime.datetime(1, 1, 1, 17, 0)): datetime.timedelta(seconds=2700),
Range[datetime.datetime(1, 1, 1, 17, 0), datetime.datetime(1, 1, 1, 18, 0)): datetime.timedelta(seconds=3000),
Range[datetime.datetime(1, 1, 1, 18, 0), datetime.datetime(1, 1, 1, 19, 0)): datetime.timedelta(seconds=600),
Range[datetime.datetime(1, 1, 1, 19, 0), datetime.datetime(1, 1, 1, 20, 0)): datetime.timedelta(0)}
, который является вашим предполагаемым результатом, представленным datetime
s.