import datetime
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
today = (now.weekday(), now.hour, now.minute)
for lecture in LECTURES:
if today < lecture:
return lecture
def get_next_lecture(now=None):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return now.replace(day=now.day + day, now.replace(hour=hour, minute=minute, second=0, microsecond=0)
+ datetime.timedelta(day - now.weekday())
)
Test code
def replace(date, changes):
day, hour, minute = changes
return date.replace(hour=hour, minute=minute) + datetime.timedelta(days=day)
def test(tests, bases, fn):
for base in bases:
date = base.replace(second=0, microsecond=0) - datetime.timedelta(days=base.weekday())
for test, exp in tests:
try:
output = fn(replace(date, test))
except Exception as e:
print(f'❌ {test=}, {exp=}')
print(' ', e)
continue
expected = replace(date, exp)
try:
assert output == expected
except AssertionError:
print(f'❌ {test=}, {exp=}')
print(' ', date, output, expected)
else:
print(f'✔️ {test=}, {exp=}')
TESTS = [
[(0, 0, 0), (0, 10, 15)],
[(0, 10, 10), (0, 10, 15)],
[(0, 10, 15), (2, 12, 15)],
[(0, 10, 20), (2, 12, 15)],
[(1, 12, 20), (2, 12, 15)],
[(1, 13, 20), (2, 12, 15)],
[(2, 10, 0), (2, 12, 15)],
[(2, 10, 14), (2, 12, 15)],
[(2, 12, 15), (3, 8, 15)],
[(3, 8, 15), (7, 10, 15)],
]
BASES = [
datetime.datetime.now(),
datetime.datetime(2020, 9, 1),
datetime.datetime(2020, 10, 1) - datetime.timedelta(days=1),
datetime.datetime(2020, 12, 1),
datetime.datetime(2021, 1, 1) - datetime.timedelta(days=1),
]
test(TESTS, BASES, get_next_lecture)
import datetime
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
today = (now.weekday(), now.hour, now.minute)
for lecture in LECTURES:
if today < lecture:
return lecture
def get_next_lecture(now=None):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return now.replace(day=now.day + day, hour=hour, minute=minute, second=0, microsecond=0)
import datetime
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
today = (now.weekday(), now.hour, now.minute)
for lecture in LECTURES:
if today < lecture:
return lecture
def get_next_lecture(now=None):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return ( now.replace(hour=hour, minute=minute, second=0, microsecond=0)
+ datetime.timedelta(day - now.weekday())
)
Test code
def replace(date, changes):
day, hour, minute = changes
return date.replace(hour=hour, minute=minute) + datetime.timedelta(days=day)
def test(tests, bases, fn):
for base in bases:
date = base.replace(second=0, microsecond=0) - datetime.timedelta(days=base.weekday())
for test, exp in tests:
try:
output = fn(replace(date, test))
except Exception as e:
print(f'❌ {test=}, {exp=}')
print(' ', e)
continue
expected = replace(date, exp)
try:
assert output == expected
except AssertionError:
print(f'❌ {test=}, {exp=}')
print(' ', date, output, expected)
else:
print(f'✔️ {test=}, {exp=}')
TESTS = [
[(0, 0, 0), (0, 10, 15)],
[(0, 10, 10), (0, 10, 15)],
[(0, 10, 15), (2, 12, 15)],
[(0, 10, 20), (2, 12, 15)],
[(1, 12, 20), (2, 12, 15)],
[(1, 13, 20), (2, 12, 15)],
[(2, 10, 0), (2, 12, 15)],
[(2, 10, 14), (2, 12, 15)],
[(2, 12, 15), (3, 8, 15)],
[(3, 8, 15), (7, 10, 15)],
]
BASES = [
datetime.datetime.now(),
datetime.datetime(2020, 9, 1),
datetime.datetime(2020, 10, 1) - datetime.timedelta(days=1),
datetime.datetime(2020, 12, 1),
datetime.datetime(2021, 1, 1) - datetime.timedelta(days=1),
]
test(TESTS, BASES, get_next_lecture)
Your algorithm seems good, but the while
loop, and lecture_hour
and lecture_minute
variables make your code a lot more complicated.
If we KISS then a simple algorithm is to just remove ()
from Lectures
and iterate through it, since it is sorted.
The first lecture that is after the current time is the lecture we want.
This is nice and simple:
import datetime
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
today if= (now.weekday() <= day
and, now.hour <=, hournow.minute)
for lecture in andLECTURES:
now.minute < minute
if today < )lecture:
return day, hour, minutelecture
def get_next_lecture(now=None):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return now.replace(day=now.day + day, hour=hour, minute=minute, second=0, microsecond=0)
From here we can see if the weekday is 4-6 then _get_next_lecture
will return nothing and so will error.
This is easy to solve, we just return the first lecture with +7
days.
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
today if= (now.weekday() <= day
and, now.hour <=, hournow.minute)
for lecture in andLECTURES:
now.minute < minute
if today < )lecture:
return day, hour, minutelecture
day, hour, minute = LECTURES[0]
return day + 7, hour, minute
With only 3 lectures there's not much point in optimizing further. However if you have more, here is some food for thought:
You can use bisect to find where to insert into in \$O(\log n)\$ time.
You can change
LECTURES
into a 7 item list with the weekday as the index and the lectures as the value (always as a list). From here you just find the date using either of the above algorithms.This would look like your
Lectures
. But with a list for each day.This has either \$O(d)\$ or \$O(\log d)\$ time where \$d\$ is the maximum amount of lectures in a day.
Your algorithm seems good, but the while
loop, and lecture_hour
and lecture_minute
variables make your code a lot more complicated.
If we KISS then a simple algorithm is to just remove ()
from Lectures
and iterate through it, since it is sorted.
The first lecture that is after the current time is the lecture we want.
This is nice and simple:
import datetime
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
if (now.weekday() <= day
and now.hour <= hour
and now.minute < minute
):
return day, hour, minute
def get_next_lecture(now=None):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return now.replace(day=now.day + day, hour=hour, minute=minute, second=0, microsecond=0)
From here we can see if the weekday is 4-6 then _get_next_lecture
will return nothing and so will error.
This is easy to solve, we just return the first lecture with +7
days.
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
if (now.weekday() <= day
and now.hour <= hour
and now.minute < minute
):
return day, hour, minute
day, hour, minute = LECTURES[0]
return day + 7, hour, minute
With only 3 lectures there's not much point in optimizing further. However if you have more, here is some food for thought:
You can use bisect to find where to insert into in \$O(\log n)\$ time.
You can change
LECTURES
into a 7 item list with the weekday as the index and the lectures as the value (always as a list). From here you just find the date using either of the above algorithms.This would look like your
Lectures
. But with a list for each day.This has either \$O(d)\$ or \$O(\log d)\$ time where \$d\$ is the maximum amount of lectures in a day.
Your algorithm seems good, but the while
loop, and lecture_hour
and lecture_minute
variables make your code a lot more complicated.
If we KISS then a simple algorithm is to just remove ()
from Lectures
and iterate through it, since it is sorted.
The first lecture that is after the current time is the lecture we want.
This is nice and simple:
import datetime
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
today = (now.weekday(), now.hour, now.minute)
for lecture in LECTURES:
if today < lecture:
return lecture
def get_next_lecture(now=None):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return now.replace(day=now.day + day, hour=hour, minute=minute, second=0, microsecond=0)
From here we can see if the weekday is 4-6 then _get_next_lecture
will return nothing and so will error.
This is easy to solve, we just return the first lecture with +7
days.
def _get_next_lecture(now):
today = (now.weekday(), now.hour, now.minute)
for lecture in LECTURES:
if today < lecture:
return lecture
day, hour, minute = LECTURES[0]
return day + 7, hour, minute
With only 3 lectures there's not much point in optimizing further. However if you have more, here is some food for thought:
You can use bisect to find where to insert into in \$O(\log n)\$ time.
You can change
LECTURES
into a 7 item list with the weekday as the index and the lectures as the value (always as a list). From here you just find the date using either of the above algorithms.This would look like your
Lectures
. But with a list for each day.This has either \$O(d)\$ or \$O(\log d)\$ time where \$d\$ is the maximum amount of lectures in a day.
Your algorithm seems good, but the while
loop, and lecture_hour
and lecture_minute
variables make your code a lot more complicated.
If we KISS then a simple algorithm is to just remove ()
from Lectures
and iterate through it, since it is sorted.
The first lecture that is after the current time is the lecture we want.
This is nice and simple:
import datetime
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
if (now.dayweekday() <= day
and now.hour <= hour
and now.minute < minute
):
return day, hour, minute
def get_next_lecture(nownow=None):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return now.replace(day=now.day + day, hour=hour, minute=minute, second=0, microsecond=0)
From here we can see if the weekday is 4-6 then _get_next_lecture
will return nothing and so will error.
This is easy to solve, we just return the first lecture with +7
days.
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
if (now.dayweekday() <= day
and now.hour <= hour
and now.minute < minute
):
return day, hour, minute
day, hour, minute = LECTURES[0]
return day + 7, hour, minute
With only 3 lectures there's not much point in optimizing further. However if you have more, here is some food for thought:
You can use bisect to find where to insert into in \$O(\log n)\$ time.
You can change
LECTURES
into a 7 item list with the weekday as the index and the lectures as the value (always as a list). From here you just find the date using either of the above algorithms.This would look like your
Lectures
. But with a list for each day.This has either \$O(d)\$ or \$O(\log d)\$ time where \$d\$ is the maximum amount of lectures in a day.
Your algorithm seems good, but the while
loop, and lecture_hour
and lecture_minute
variables make your code a lot more complicated.
If we KISS then a simple algorithm is to just remove ()
from Lectures
and iterate through it, since it is sorted.
The first lecture that is after the current time is the lecture we want.
This is nice and simple:
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
if (now.day <= day
and now.hour <= hour
and now.minute < minute
):
return day, hour, minute
def get_next_lecture(now):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return now.replace(day=now.day + day, hour=hour, minute=minute, second=0, microsecond=0)
From here we can see if the weekday is 4-6 then _get_next_lecture
will return nothing and so will error.
This is easy to solve, we just return the first lecture with +7
days.
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
if (now.day <= day
and now.hour <= hour
and now.minute < minute
):
return day, hour, minute
day, hour, minute = LECTURES[0]
return day + 7, hour, minute
With only 3 lectures there's not much point in optimizing further. However if you have more, here is some food for thought:
You can use bisect to find where to insert into in \$O(\log n)\$ time.
You can change
LECTURES
into a 7 item list with the weekday as the index and the lectures as the value (always as a list). From here you just find the date using either of the above algorithms.This would look like your
Lectures
. But with a list for each day.This has either \$O(d)\$ or \$O(\log d)\$ time where \$d\$ is the maximum amount of lectures in a day.
Your algorithm seems good, but the while
loop, and lecture_hour
and lecture_minute
variables make your code a lot more complicated.
If we KISS then a simple algorithm is to just remove ()
from Lectures
and iterate through it, since it is sorted.
The first lecture that is after the current time is the lecture we want.
This is nice and simple:
import datetime
LECTURES = [(0, 10, 15), (2, 12, 15), (3, 8, 15)]
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
if (now.weekday() <= day
and now.hour <= hour
and now.minute < minute
):
return day, hour, minute
def get_next_lecture(now=None):
if now is None:
now = datetime.datetime.now()
day, hour, minute = _get_next_lecture(now)
return now.replace(day=now.day + day, hour=hour, minute=minute, second=0, microsecond=0)
From here we can see if the weekday is 4-6 then _get_next_lecture
will return nothing and so will error.
This is easy to solve, we just return the first lecture with +7
days.
def _get_next_lecture(now):
for day, hour, minute in LECTURES:
if (now.weekday() <= day
and now.hour <= hour
and now.minute < minute
):
return day, hour, minute
day, hour, minute = LECTURES[0]
return day + 7, hour, minute
With only 3 lectures there's not much point in optimizing further. However if you have more, here is some food for thought:
You can use bisect to find where to insert into in \$O(\log n)\$ time.
You can change
LECTURES
into a 7 item list with the weekday as the index and the lectures as the value (always as a list). From here you just find the date using either of the above algorithms.This would look like your
Lectures
. But with a list for each day.This has either \$O(d)\$ or \$O(\log d)\$ time where \$d\$ is the maximum amount of lectures in a day.