コード例 #1
0
def fill_gaps(current_time, current_day_start, current_day_end, next_block,
              blocks):
    """
	@brief      fills the range r for current_times < r < next_block.start_time

	@param      current_time(arrow): the end_time of the last placed TimeBlock
	@param      current_day_start(arrow): the start_time of a day within our date/time range
	@param      current_day_end(arrow): the end_time of a day within our date/time range
	@param      next_block(TimeBlock): The next busy block we will encounter
	@param 		blocks(list): list of TimeBlock Objects

	@return     None, updates the list 'blocks' by adding free TimeBlock Objects
	"""
    next_day = int(next_block.get_start_time().format("DD"))
    while int(current_time.format("DD")) != next_day:
        free_block = timeblocks.TimeBlock(current_time, current_day_end)
        if current_time != current_day_end:
            blocks.append(free_block)
        current_day_start = current_day_start.shift(days=+1)
        current_day_end = current_day_end.shift(days=+1)
        current_time = current_day_start

    # Fill our the rest of the days time with a free block
    if current_time != next_block.get_start_time():
        free_block = timeblocks.TimeBlock(current_time,
                                          next_block.get_start_time())
        blocks.append(free_block)

    return None
コード例 #2
0
def test_within():
	block1 = timeblocks.TimeBlock(arrow.get("2017-11-07T12:00:00-08:00"),arrow.get("2017-11-07T15:00:00-08:00"), "Block 1")
	block2 = timeblocks.TimeBlock(arrow.get("2017-11-07T15:01:00-08:00"),arrow.get("2017-11-07T17:00:00-08:00"), "Block 2")
	block3 = timeblocks.TimeBlock(arrow.get("2017-11-07T11:00:00-08:00"),arrow.get("2017-11-07T16:00:00-08:00"), "Block 3")

	assert(block3.is_within(block2))
	assert(block3.is_within(block1))
	assert(not (block2.is_within(block1)))
コード例 #3
0
def get_busy(service,calendar_id,begin_date,end_date,unique_id = None):
    """
    @brief      creates a list of busy times using events for ONE Google Calendar

    @param      service: Google 'service' object
    @param      calendar_id: a specific Google calendar's id
    @param      begin_date (arrow): beginning of busy times date range
    @param      end_date (arrow): end of busy times date range
    @param      unique_id: specific id of a recurring Google calendar event

    @return     a list of events from a calendar(event_description,start_str,end_str) that which a person is marked "busy"

    """
    busy_events = []
    page_token = None
    i = 0
    while True:
        # Events: list (https://developers.google.com/google-apps/calendar/v3/reference/events/list#examples)
        if unique_id:
            events = service.events().instances(calendarId=calendar_id, eventId=unique_id,pageToken=page_token).execute()
        else:
            events = service.events().list(calendarId=calendar_id,pageToken=page_token).execute()
        for event in events['items']:
            event_description = None
            # the 'transparency' key will only be present for calendar events marked: Show me as Available
            # Thus the condition below with result true when an event is marked
            # Show me as: Busy
            if "transparency" in event:
                continue
            # The "recurrence" key will be present in events that repeat multiple times (i.e. once a week). We must individually
            # loop thorugh each of these events by their unique_id in order to get the appropriate times and dates
            if "recurrence" in event:
                busy_events += get_busy(service,calendar_id,begin_date,end_date,event["id"])
                continue
            # Get a text field that describes the event
            try:
                event_description = event["summary"]
                # the 'date' field will only be present for events that last a whole day.
                # Otherwise a 'datetime' will be present
                if "date" in event['start']:
                    start = event['start']['date'] # Date format is YYYY-DD-MM
                    end = event['start']['date'] # Date format is YYYY-DD-MM
                else:
                    start = event['start']['dateTime'] # dateTime format is YYYY-MM-DD HH:mm:ss ZZ
                    end = event['end']['dateTime'] # dateTime format is YYYY-MM-DD HH:mm:ss ZZ
                # Create arrow objects for event start, end and the daterange
                event_start = arrow.get(start)
                event_end = arrow.get(end)
                window = timeblocks.TimeBlock(begin_date,end_date)
                event = timeblocks.TimeBlock(event_start,event_end,event_description)
                if event.is_within(window):
                    busy_events.append(event.get_overlap(window))
            except KeyError:
                print("Key Error")
        page_token = events.get('nextPageToken')
        if not page_token:
            break
    return busy_events
コード例 #4
0
def consolidate(busy_blocks):
    """
	@brief      consolidates the list of TimeBlocks

	@param      busy_blocks: list of TimeBlock Objects, representing busy times

	@return     a list of busy_blocks where overlapping TimeBlocks have been merged together
	"""
    consolidated = []
    prev = None
    for block in busy_blocks:
        if prev == None:
            prev = block
        # Case: There is a 'gap' between when the last block ended and the current starts
        elif prev.get_end_time() < block.get_start_time():
            consolidated.append(prev)
            prev = block
        # Case: There is some overlap between the two blocks
        else:
            description = prev.merge_descriptions(block)
            greater_end = max(prev.get_end_time(), block.get_end_time())
            block = timeblocks.TimeBlock(prev.get_start_time(), greater_end,
                                         description)
        prev = block
    consolidated.append(prev)

    return consolidated
コード例 #5
0
def test_overlap():
	block1 = timeblocks.TimeBlock(arrow.get("2017-11-07T12:00:00-08:00"),arrow.get("2017-11-07T15:00:00-08:00"), "Block 1")
	block2 = timeblocks.TimeBlock(arrow.get("2017-11-07T10:00:00-08:00"),arrow.get("2017-11-07T12:01:00-08:00"), "Block 2")
	block3 = timeblocks.TimeBlock(arrow.get("2017-11-07T09:00:00-08:00"),arrow.get("2017-11-07T16:00:00-08:00"))
	block4 = timeblocks.TimeBlock(arrow.get("2017-11-07T15:00:00-08:00"),arrow.get("2017-11-07T23:00:00-08:00"))

	assert(block1.get_overlap(block2) == timeblocks.TimeBlock(arrow.get("2017-11-07T12:00:00-08:00"),
												arrow.get("2017-11-07T12:01:00-08:00"),
												"Block 1, Block 2"))

	assert(block2.get_overlap(block3) == timeblocks.TimeBlock(arrow.get("2017-11-07T10:00:00-08:00"),arrow.get("2017-11-07T12:01:00-08:00"),"Block 2"))
	assert(block4.get_overlap(block1) == timeblocks.TimeBlock(arrow.get("2017-11-07T15:00:00-08:00"),arrow.get("2017-11-07T15:00:00-08:00"),"Block 1"))
コード例 #6
0
def test_consolidate():
    block1 = timeblocks.TimeBlock(arrow.get("2017-11-07T07:00:00-08:00"),
                                  arrow.get("2017-11-07T10:15:00-08:00"),
                                  "Block 1")
    block2 = timeblocks.TimeBlock(arrow.get("2017-11-07T10:15:00-08:00"),
                                  arrow.get("2017-11-07T13:45:00-08:00"),
                                  "Block 2")
    block3 = timeblocks.TimeBlock(arrow.get("2017-11-07T10:30:00-08:00"),
                                  arrow.get("2017-11-07T11:30:00-08:00"),
                                  "Block 3")

    block4 = timeblocks.TimeBlock(arrow.get("2017-11-08T08:30:00-08:00"),
                                  arrow.get("2017-11-08T10:30:00-08:00"),
                                  "Block 4")
    block5 = timeblocks.TimeBlock(arrow.get("2017-11-08T09:30:00-08:00"),
                                  arrow.get("2017-11-08T12:00:00-08:00"))
    block6 = timeblocks.TimeBlock(arrow.get("2017-11-08T15:30:00-08:00"),
                                  arrow.get("2017-11-08T17:00:00-08:00"),
                                  "Block 6")

    block_list = [block1, block2, block3, block4, block5, block6]
    c_list = calc_free_times.consolidate(block_list)

    correct = [
        timeblocks.TimeBlock(arrow.get("2017-11-07T07:00:00-08:00"),
                             arrow.get("2017-11-07T13:45:00-08:00"),
                             "Block 1, Block 2, Block 3"),
        timeblocks.TimeBlock(arrow.get("2017-11-08T08:30:00-08:00"),
                             arrow.get("2017-11-08T12:00:00-08:00"),
                             "Block 4"),
        timeblocks.TimeBlock(arrow.get("2017-11-08T15:30:00-08:00"),
                             arrow.get("2017-11-08T17:00:00-08:00"), "Block 6")
    ]

    assert (correct == c_list)

    assert (calc_free_times)
コード例 #7
0
def get_time_blocks(busy_blocks, begin_date, end_date, begin_time, end_time):
    """
	@brief      Calculates a list of TimeBlocks (Free and Busy)

	@param      busy_blocks(list of TimeBlock Objects)  The list of busy times
    @param      begin_date (str): beginning date of date range. ISO formated date EX. 2017-11-15T00:00:00-08:00
    @param      end_date (str): ending day of date range. ISO formated date EX. 2017-11-21T00:00:00-08:00
    @param      begin_time (str): beginning time of time range. Format HH:mm EX. 08:00
    @param      end_time (str): ending time of time range. Format HH:mm EX. 17:00

	@return     A List of TimeBlocks (free and busy sorted in ascending order)
	"""
    # Setup arrow objects for time and date range
    begin_hr, begin_min = list(map(int, begin_time.split(":")))
    end_hr, end_min = list(map(int, end_time.split(":")))
    open_time = arrow.get(begin_date).replace(hour=begin_hr, minute=begin_min)
    open_year, open_month, open_day = list(
        map(int,
            open_time.format("YYYY:MM:DD").split(":")))
    end_time = arrow.get(end_date).replace(hour=end_hr, minute=end_min)

    # consolidate and trim the list of busy_blocks
    consolidated = consolidate(busy_blocks)
    trimmed = trim_blocks(consolidated, open_time, end_time)

    # add free TimeBlocks
    pointer = open_time
    current_day_start = open_time
    current_day_end = end_time.replace(year=open_year,
                                       month=open_month,
                                       day=open_day)
    times = []  # blocked times
    for block in trimmed:
        # Case: our pointer is at the end of a day's time range
        if pointer == current_day_end:
            current_day_start = current_day_start.shift(days=+1)
            current_day_end = current_day_end.shift(days=+1)
            pointer = current_day_start
        if pointer.time == block.get_start_time():
            pointer.time == block.get_end_time()
        # Pointer and current event are on same day
        if int(pointer.format("DD")) == int(
                block.get_start_time().format("DD")):
            free_block = timeblocks.TimeBlock(pointer, block.get_start_time())
            pointer = block.get_end_time()
            times.append(free_block)
        # Idea: stall going onto next block unitl pointer reaches current block_end and has filled that space with free time blocks
        else:
            fill_gaps(pointer, current_day_start, current_day_end, block,
                      times)
            pointer = block.get_end_time()
            y, m, d = list(map(int, pointer.format("YYYY:MM:DD").split(":")))
            current_day_start = current_day_start.replace(year=y,
                                                          month=m,
                                                          day=d)
            current_day_end = current_day_end.replace(year=y, month=m, day=d)

        times.append(block)
    # If the last Event ends before the window closes, make the rest free TimeBlocks
    if pointer != end_time:
        fill_gaps(pointer, current_day_start, current_day_end,
                  timeblocks.TimeBlock(end_time, None), times)
    return times
コード例 #8
0
def trim_day(event_block, day_slices, event_slices):
    """
	@brief      Trims a TimeBlock so that it properly fits the time and date range

	@param      event_block(TimeBlock)  A TimeBlock object
	@param      day_slices (list):  created by the function "create_daily_slices"

	@return     a list of TimeBlocks, each trimmed to fit the bounds of time range.

				For Example. A timeblock from 8:00 am - 4:00 pm would be trimmed down to
				9:00am - 3:00pm when the given timerange is 9:00am-3:00pm. Addittionally, one
				event that spans over multiple days will be split into separate time blocks. One for each day
	"""
    trimmed_blocks = []
    day_start = day_slices[0]
    event_start = event_slices[0]
    l = 0
    r = 0
    while day_start.format("YYYY/MM/DD") != event_start.format("YYYY/MM/DD"):
        if day_start < event_start:
            l += 1
            day_start = day_start.shift(days=+1)
        else:
            r += 1
            event_start = event_start.shift(days=+1)
    l *= 2
    r *= 2

    while l < len(day_slices) and r < len(event_slices):
        day_start = day_slices[l]
        day_end = day_slices[l + 1]
        event_start = event_slices[r]
        event_end = event_slices[r + 1]
        # The event_block will lay within no more of our slices
        if day_start > event_end:
            break
        # The event starts before and ends after our date/time range, just add the whole date/time range
        elif event_start <= day_start and event_end >= day_end:
            trimmed_blocks.append(
                timeblocks.TimeBlock(day_start, day_end,
                                     event_block.get_description()))
        # The event is completely within our slice
        elif day_start <= event_start and day_end >= event_end:
            trimmed_blocks.append(
                timeblocks.TimeBlock(event_start, event_end,
                                     event_block.get_description()))
            # break
        elif (event_start <= day_start) and (event_end <= day_end) and (
                event_end >= day_start):
            trimmed_blocks.append(
                timeblocks.TimeBlock(day_start, event_end,
                                     event_block.get_description()))
            # break
        elif day_start <= event_start and event_end >= day_end and event_start <= day_end:
            trimmed_blocks.append(
                timeblocks.TimeBlock(event_start, day_end,
                                     event_block.get_description()))
        l += 2
        r += 2

    return trimmed_blocks
コード例 #9
0
def test_get():
	block1 = timeblocks.TimeBlock(arrow.get("2017-11-07T14:00:00-08:00"),arrow.get("2017-11-07T15:00:00-08:00"), "Block 1")
	assert(block1.get_description() == "Block 1")
	assert(block1.get_start_time() == arrow.get("2017-11-07T14:00:00-08:00"))
	assert(block1.get_end_time() == arrow.get("2017-11-07T15:00:00-08:00"))
コード例 #10
0
def test_append():
	block1 = timeblocks.TimeBlock(arrow.get("2017-11-07T12:00:00-08:00"),arrow.get("2017-11-07T15:00:00-08:00"), "Block 1")
	block2 = timeblocks.TimeBlock(arrow.get("2017-11-07T15:00:00-08:00"),arrow.get("2017-11-07T17:00:00-08:00"), "Block 2")
	assert(block1.append_block(block2) == timeblocks.TimeBlock(arrow.get("2017-11-07T12:00:00-08:00"),arrow.get("2017-11-07T17:00:00-08:00"),"Block 1, Block 2"))
コード例 #11
0
def test_trim():
    ### Test Cases for trim_day
    timerange_open = arrow.get("2017-10-08T08:20:00-08:00")
    timerange_close = arrow.get("2017-10-18T11:59:00-08:00")

    block = timeblocks.TimeBlock(arrow.get("2017-10-07T06:30:00-08:00"),
                                 arrow.get("2017-10-14T10:08:00-08:00"),
                                 "Away on Holiday")
    slices = calc_free_times.create_daily_slices(timerange_open,
                                                 timerange_close)
    event_slices = calc_free_times.create_daily_slices(block.get_start_time(),
                                                       block.get_end_time())
    trimmed = calc_free_times.trim_day(block, slices, event_slices)

    correct = [
        timeblocks.TimeBlock(arrow.get("2017-10-08T08:20:00-08:00"),
                             arrow.get("2017-10-08T10:08:00-08:00"),
                             "Away on Holiday"),
        timeblocks.TimeBlock(arrow.get("2017-10-09T08:20:00-08:00"),
                             arrow.get("2017-10-09T10:08:00-08:00"),
                             "Away on Holiday"),
        timeblocks.TimeBlock(arrow.get("2017-10-10T08:20:00-08:00"),
                             arrow.get("2017-10-10T10:08:00-08:00"),
                             "Away on Holiday"),
        timeblocks.TimeBlock(arrow.get("2017-10-11T08:20:00-08:00"),
                             arrow.get("2017-10-11T10:08:00-08:00"),
                             "Away on Holiday"),
        timeblocks.TimeBlock(arrow.get("2017-10-12T08:20:00-08:00"),
                             arrow.get("2017-10-12T10:08:00-08:00"),
                             "Away on Holiday"),
        timeblocks.TimeBlock(arrow.get("2017-10-13T08:20:00-08:00"),
                             arrow.get("2017-10-13T10:08:00-08:00"),
                             "Away on Holiday"),
        timeblocks.TimeBlock(arrow.get("2017-10-14T08:20:00-08:00"),
                             arrow.get("2017-10-14T10:08:00-08:00"),
                             "Away on Holiday")
    ]
    assert (trimmed == correct)

    block2 = timeblocks.TimeBlock(arrow.get("2017-10-14T05:30:00-08:00"),
                                  arrow.get("2017-10-14T20:15:00-08:00"),
                                  "Busy All Day")
    event_slices = calc_free_times.create_daily_slices(block2.get_start_time(),
                                                       block2.get_end_time())
    trimmed = calc_free_times.trim_day(block2, slices, event_slices)

    correct = [
        timeblocks.TimeBlock(arrow.get("2017-10-14T08:20:00-08:00"),
                             arrow.get("2017-10-14T11:59:00-08:00"),
                             "Busy All Day")
    ]
    assert (trimmed == correct)

    block3 = timeblocks.TimeBlock(arrow.get("2017-10-18T10:30:00-08:00"),
                                  arrow.get("2017-10-18T20:15:00-08:00"),
                                  "Busy 1/2 Day")
    event_slices = calc_free_times.create_daily_slices(block3.get_start_time(),
                                                       block3.get_end_time())
    trimmed = calc_free_times.trim_day(block2, slices, event_slices)

    correct = [
        timeblocks.TimeBlock(arrow.get("2017-10-18T10:30:00-08:00"),
                             arrow.get("2017-10-18T11:59:00-08:00"),
                             "Busy 1/2 Day")
    ]

    ### Test case for trim_blocks
    timerange_open = arrow.get("2017-11-07T10:20:00-08:00")
    timerange_close = arrow.get("2017-11-11T15:59:00-08:00")

    blocks = [
        timeblocks.TimeBlock(arrow.get("2017-11-07T07:00:00-08:00"),
                             arrow.get("2017-11-07T13:45:00-08:00"),
                             "Block 1, Block 2, Block 3"),
        timeblocks.TimeBlock(arrow.get("2017-11-10T15:30:00-08:00"),
                             arrow.get("2017-11-12T17:00:00-08:00"), "Block 6")
    ]

    trimmed = calc_free_times.trim_blocks(blocks, timerange_open,
                                          timerange_close)

    correct = [
        timeblocks.TimeBlock(arrow.get("2017-11-07T10:20:00-08:00"),
                             arrow.get("2017-11-07T13:45:00-08:00"),
                             "Block 1, Block 2, Block 3"),
        timeblocks.TimeBlock(arrow.get("2017-11-10T15:30:00-08:00"),
                             arrow.get("2017-11-10T15:59:00-08:00"),
                             "Block 6"),
        timeblocks.TimeBlock(arrow.get("2017-11-11T15:30:00-08:00"),
                             arrow.get("2017-11-11T15:59:00-08:00"), "Block 6")
    ]

    assert (trimmed == correct)
コード例 #12
0
def test_free_times():
    begin_date = "2017-10-07T00:00:00-08:00"
    begin_time = "06:15"
    end_date = "2017-10-11T00:00:00-08:00"
    end_time = "15:59"

    busy_blocks = [
        timeblocks.TimeBlock(arrow.get("2017-10-08T08:20:00-08:00"),
                             arrow.get("2017-10-08T10:00:00-08:00"), "B2"),
        timeblocks.TimeBlock(arrow.get("2017-10-09T06:15:00-08:00"),
                             arrow.get("2017-10-09T15:59:00-08:00"), "B1"),
        timeblocks.TimeBlock(arrow.get("2017-10-10T13:55:00-08:00"),
                             arrow.get("2017-10-10T15:59:00-08:00"), "B4")
    ]
    blocks = calc_free_times.get_time_blocks(busy_blocks, begin_date, end_date,
                                             begin_time, end_time)

    correct = [
        timeblocks.TimeBlock(arrow.get("2017-10-07T06:15:00-08:00"),
                             arrow.get("2017-10-07T15:59:00-08:00")),
        timeblocks.TimeBlock(arrow.get("2017-10-08T06:15:00-08:00"),
                             arrow.get("2017-10-08T08:20:00-08:00")),
        timeblocks.TimeBlock(arrow.get("2017-10-08T08:20:00-08:00"),
                             arrow.get("2017-10-08T10:00:00-08:00"), "B2"),
        timeblocks.TimeBlock(arrow.get("2017-10-08T10:00:00-08:00"),
                             arrow.get("2017-10-08T15:59:00-08:00")),
        timeblocks.TimeBlock(arrow.get("2017-10-09T06:15:00-08:00"),
                             arrow.get("2017-10-09T15:59:00-08:00"), "B1"),
        timeblocks.TimeBlock(arrow.get("2017-10-10T06:15:00-08:00"),
                             arrow.get("2017-10-10T13:55:00-08:00")),
        timeblocks.TimeBlock(arrow.get("2017-10-10T13:55:00-08:00"),
                             arrow.get("2017-10-10T15:59:00-08:00"), "B4"),
        timeblocks.TimeBlock(arrow.get("2017-10-11T06:15:00-08:00"),
                             arrow.get("2017-10-11T15:59:00-08:00"))
    ]
    assert (blocks == correct)