Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
First solution in Clear category for Crontab Parsing by mortonfox
from datetime import datetime, timedelta
specials = {
'@yearly': '0 0 1 1 *',
'@annually': '0 0 1 1 *',
'@monthly': '0 0 1 * *',
'@weekly': '0 0 * * 0',
'@daily': '0 0 * * *',
'@midnight': '0 0 * * *',
'@hourly': '0 * * * *'
}
fields = [
{ 'name': 'minute', 'low': 0, 'high': 59, 'alt': [] },
{ 'name': 'hour', 'low': 0, 'high': 23, 'alt': [] },
{ 'name': 'day of month', 'low': 1, 'high': 31, 'alt': [] },
{ 'name': 'month', 'low': 1, 'high': 12, 'alt': 'JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC'.split() },
{ 'name': 'day of week', 'low': 0, 'high': 6, 'alt': 'SUN MON TUE WED THU FRI SAT'.split() }
]
def parse(crontab):
parse_item = lambda item, field: field['alt'].index(item.upper()) + field['low'] if item.upper() in field['alt'] else int(item)
res = {}
for field, st in zip(fields, crontab.split()):
items = set()
for st1 in st.split(','):
rnge, step = (st1.split('/') + [1])[:2]
ary = []
if rnge == '*':
ary = list(range(field['low'], field['high'] + 1))
elif '-' in rnge:
r1, r2 = [parse_item(r, field) for r in rnge.split('-')]
ary = list(range(r1, r2 + 1))
else:
ary = [parse_item(rnge, field)]
items = items.union(ary[::int(step)])
res[field['name']] = items
return res
def next_crontab_exec(crontab_time: str, current_time_str: str) -> list[str]:
dt = datetime.strptime(current_time_str, '%Y-%m-%dT%H:%M')
cronspec = parse(specials[crontab_time]) if crontab_time in specials else parse(crontab_time)
res = []
while len(res) < 3:
dt += timedelta(minutes=1)
if dt.minute in cronspec['minute'] and dt.hour in cronspec['hour'] and dt.day in cronspec['day of month'] and dt.month in cronspec['month'] and dt.isoweekday() % 7 in cronspec['day of week']:
res.append(dt.strftime('%Y-%m-%dT%H:%M'))
return res
print("Example:")
print(next_crontab_exec("* * * * *", "2025-03-03T14:30"))
# These "asserts" are used for self-checking
assert next_crontab_exec("* * * * *", "2025-03-03T14:30") == [
"2025-03-03T14:31",
"2025-03-03T14:32",
"2025-03-03T14:33",
]
assert next_crontab_exec("*/15 * * * *", "2025-03-03T14:30") == [
"2025-03-03T14:45",
"2025-03-03T15:00",
"2025-03-03T15:15",
]
assert next_crontab_exec("5,10,15,20 * * * *", "2025-03-03T14:07") == [
"2025-03-03T14:10",
"2025-03-03T14:15",
"2025-03-03T14:20",
]
assert next_crontab_exec("10-20 * * * *", "2025-03-03T14:05") == [
"2025-03-03T14:10",
"2025-03-03T14:11",
"2025-03-03T14:12",
]
assert next_crontab_exec("10-30/5 * * * *", "2025-03-03T14:12") == [
"2025-03-03T14:15",
"2025-03-03T14:20",
"2025-03-03T14:25",
]
assert next_crontab_exec("@daily", "2025-03-03T14:30") == [
"2025-03-04T00:00",
"2025-03-05T00:00",
"2025-03-06T00:00",
]
print("The mission is done! Click 'Check Solution' to earn rewards!")
March 10, 2025
Comments: