Skip to content

Instantly share code, notes, and snippets.

@kistters
Last active February 14, 2021 06:53
Show Gist options
  • Save kistters/de0729af4e9175982f1c59496332e466 to your computer and use it in GitHub Desktop.
Save kistters/de0729af4e9175982f1c59496332e466 to your computer and use it in GitHub Desktop.
Time: Split time chunks, check overlap
def at_time(t):
return time(hour=int(t.split(':')[0]), minute=int(t.split(':')[1]))
def r_time(r):
return at_time(r.split('~')[0]), at_time(r.split('~')[1]),
def fmt(start, end):
return f'{start.strftime("%H:%M")} ~ {end.strftime("%H:%M")}'
def splitter(expedient: Tuple[time, time], scheduled_events: List[Tuple[time, time]]):
""" expedient
|-----------------------|
|---inner---|
|---left---------|-------right---|
1 2 3 4 5 6 7 8 9 10 11 12
"""
if not len(scheduled_events):
return [expedient]
expedient_start, expedient_end = expedient
event_start, event_end = scheduled_events[0]
# print(f'entrou: {fmt(*expedient)} --- tirar: {[fmt(*event) for event in scheduled_events]}')
if not check_overlap(expedient, (event_start, event_end)):
print(f'voltou: {fmt(*expedient)}')
return [expedient]
# inner
if expedient_start <= event_start and expedient_end >= event_end:
print(f'{"> >" * 2} inner: {expedient_start} < {event_start} and {expedient_end} > {event_end}')
expedient_left = splitter((expedient_start, event_start), scheduled_events[1:]) if expedient_start != event_start else []
expedient_right = splitter((event_end, expedient_end), scheduled_events[1:]) if expedient_end != event_end else []
print(f'voltou: {expedient_left} + {expedient_right}')
return expedient_left + expedient_right
# left
if expedient_start > event_start and expedient_end >= event_end:
print(f'{"> >" * 2} left: {expedient_start} > {event_start} and {expedient_end} >= {event_end}')
return splitter((event_end, expedient_end), scheduled_events[1:])
# right
if expedient_start <= event_start and expedient_end < event_end:
print(f'{"> >" * 2} right: {expedient_start} <= {event_start} and {expedient_end} < {event_end}')
return splitter((expedient_start, event_start), scheduled_events[1:])
print(f'voltou 2: {expedient}')
return []
for expedient, events in [
(r_time('01:00 ~ 03:00'), [r_time('04:40 ~ 05:10')]), # nothing
(r_time('01:00 ~ 03:00'), [r_time('01:40 ~ 02:10')]), # intersection
(r_time('01:00 ~ 03:00'), [r_time('01:00 ~ 01:30')]), # lef
(r_time('01:00 ~ 03:00'), [r_time('02:30 ~ 03:00')]), # right
(r_time('01:00 ~ 03:00'), [r_time('00:00 ~ 04:00')]), # zero
(r_time('01:00 ~ 05:00'), [r_time('00:30 ~ 01:30'),
r_time('03:00 ~ 03:30'),
r_time('04:30 ~ 05:30')]),
(r_time('01:00 ~ 05:00'), [])
]:
print('')
print('*' * 5)
print(f'expedient: {fmt(*expedient)}')
print(f'events: {[fmt(*r) for r in events]} ')
# print(splitter(expedient, events))
print(f'available: {[fmt(*r) for r in splitter(expedient, events)]}')
from datetime import datetime, date, time, timedelta
from typing import Tuple
def _overlap_check(first_interval: Tuple[any, any], second_interval: Tuple[any, any]) ->bool:
first_start, first_end = first_interval
second_start, second_end = second_interval
return first_start <= second_end and second_start <= first_end
def time_overlap(first_interval: Tuple[time, time], second_interval: Tuple[time, time]) -> bool:
return _overlap_check(first_interval, second_interval)
def date_overlap(first_interval: Tuple[date, date], second_interval: Tuple[date, date]) -> bool:
return _overlap_check(first_interval, second_interval)
def increase_time_in(start_at: time, hours: float = 0, minutes: float = 0) -> time:
dt = datetime.combine(date.today(), start_at) + timedelta(**dict(hours=hours, minutes=minutes))
return dt.time()
def to_datetime(time_at: time):
return datetime.combine(date.today(), time_at)
def divide_time_interval_in(start_at: time, end_at: time, hours: float = 0, minutes: float = 0,
coffee_break: float = 0) -> list:
def _next_start(dt: datetime) -> datetime:
return to_datetime(increase_time_in(dt.time(), hours=hours, minutes=minutes))
dt_start = to_datetime(start_at)
dt_end = to_datetime(end_at)
result = []
while _next_start(dt_start) <= dt_end:
result.append((dt_start.time(), _next_start(dt_start).time()))
dt_start = _next_start(dt_start) + timedelta(minutes=coffee_break)
return result
#
# def get_time(t_string) -> time:
# """ get_time('20:30') -> time """
# hour, minute = t_string.split(':')
# return time(hour=int(hour), minute=int(minute))
def get_time(t): return time(hour=int(t.split(':')[0]), minute=int(t.split(':')[1]))
def get_date(t): return date(day=int(t.split('-')[0]), month=int(t.split('-')[1]), year=int(t.split('-')[2]))
if __name__ == '__main__':
assert get_time('12:55') == increase_time_in(get_time('10:30'), hours=2, minutes=25)
assert 6 == len(divide_time_interval_in(get_time('09:00'), get_time('15:20'), hours=1))
assert 5 == len(divide_time_interval_in(get_time('09:00'), get_time('15:20'), hours=1, coffee_break=20))
assert 4 == len(divide_time_interval_in(get_time('09:00'), get_time('15:20'), hours=1, coffee_break=40))
assert 3 == len(divide_time_interval_in(get_time('09:00'), get_time('15:20'), hours=1, coffee_break=80))
time_interval_a = (get_time('10:30'), get_time('12:30'))
time_interval_b = (get_time('12:30'), get_time('14:30'))
time_interval_c = (get_time('12:31'), get_time('14:30'))
assert time_overlap(time_interval_a, time_interval_b)
assert not time_overlap(time_interval_a, time_interval_c)
date_interval_a = (get_date('01-01-2000'), get_date('05-01-2000'))
date_interval_b = (get_date('03-01-2000'), get_date('10-01-2000'))
date_interval_c = (get_date('05-01-2000'), get_date('10-01-2000'))
date_interval_d = (get_date('06-01-2000'), get_date('10-01-2000'))
assert date_overlap(date_interval_a, date_interval_b)
assert date_overlap(date_interval_a, date_interval_c)
assert not date_overlap(date_interval_a, date_interval_d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment