Python - Algorithm find time slots

algorithm, datetime, python

Solution

#time_slots.py
from datetime import datetime, timedelta

appointments = [(datetime(2012, 5, 22, 10), datetime(2012, 5, 22, 10, 30)),
                (datetime(2012, 5, 22, 12), datetime(2012, 5, 22, 13)),
                (datetime(2012, 5, 22, 15, 30), datetime(2012, 5, 22, 17, 10))]

hours = (datetime(2012, 5, 22, 9), datetime(2012, 5, 22, 18))

def get_slots(hours, appointments, duration=timedelta(hours=1)):
    slots = sorted([(hours[0], hours[0])] + appointments + [(hours[1], hours[1])])
    for start, end in ((slots[i][1], slots[i+1][0]) for i in range(len(slots)-1)):
        assert start <= end, "Cannot attend all appointments"
        while start + duration <= end:
            print "{:%H:%M} - {:%H:%M}".format(start, start + duration)
            start += duration

if __name__ == "__main__":
    get_slots(hours, appointments)


% python time_slots.py 
09:00 - 10:00
10:30 - 11:30
13:00 - 14:00
14:00 - 15:00

Problem

Let's say today I work from 09:00 to 18:00, I have 3 appointments: - 10:00 - 10:30 - 12:00 - 13:00 - 15:30 - 17:10 I need to find a list of available time slots of 1 hour in the day. Here is the list that I should get - 09:00 - 10:00 - 10:30 - 11:30 - 13:00 - 14:00 - 14:00 - 15:00 I have already implemented that in php and I just tried to put it in python. Here is my try: ``` def get_slots(areas, duration): slots = [] for area in areas: if area['start'] == area['end']: continue i = area['start'] while (i + duration) <= area['end']: i += duration slots.append({ 'start': (i - duration), 'end': i, }) return slots def get_areas(day_start, day_end, appts): areas = [] old_end = day_start for appt in appts: if appt['start'] > old_end: areas.append({ 'start': old_end, 'end': appt['start'], }) old_end = appt['end'] if old_end > day_end: return areas areas.append({ 'start': old_end, 'end': day_end, }) return areas ``` Test: ``` >>> day_start = datetime.datetime(2012, 5, 22, 9) >>> day_end = datetime.datetime(2012, 5, 22, 18) >>> appts = [{ 'start': datetime.datetime(2012, 5, 22, 10), 'end': datetime.datetime(2012, 5, 22, 10, 30), },{ 'start': datetime.datetime(2012, 5, 22, 12), 'end': datetime.datetime(2012, 5, 22, 13), },{ 'start': datetime.datetime(2012, 5, 22, 15, 30), 'end': datetime.datetime(2012, 5, 22, 17, 10), },] >>> duration = datetime.timedelta(hours=1) >>> pprint.pprint(get_slots(get_areas(day_start, day_end, appts), duration)) ``` It works, but I simply ported the code from php. So I'm not sure it's a pythonist way to do it. Can you show me where I can improve ?

Original source