|
import sys |
|
import csv |
|
from datetime import datetime, timedelta |
|
from zoneinfo import ZoneInfo |
|
from icalendar import Calendar, Event |
|
|
|
ENABLED_COURSES = [ |
|
2, 3, 4, # essential one |
|
9, # algebra |
|
25, # gpu |
|
26 # mpp |
|
] |
|
|
|
REPEAT_UNTIL = "2026-01-01" |
|
SEMESTER_START = "2025-09-01" |
|
MSK = ZoneInfo("Europe/Moscow") |
|
|
|
def parse_time(s): |
|
weekdays = { |
|
'понедельник': 0, 'вторник': 1, 'среда': 2, |
|
'четверг': 3, 'пятница': 4, 'суббота': 5, 'воскресенье': 6 |
|
} |
|
import re |
|
m = re.search(r'(понедельник|вторник|среда|четверг|пятница|суббота|воскресенье)' |
|
r'.*?(\d{1,2}[:.]\d{2})\s*[-–]\s*(\d{1,2}[:.]\d{2})?', s, re.I) |
|
if not m: |
|
return None |
|
day, t1, t2 = m.group(1).lower(), m.group(2), m.group(3) |
|
dow = weekdays[day] |
|
start = datetime.strptime(t1.replace('.', ':'), '%H:%M').time() |
|
end = datetime.strptime((t2 or t1).replace('.', ':'), '%H:%M').time() |
|
return dow, start, end |
|
|
|
def find_first_day(target_dow): |
|
dt = datetime.fromisoformat(SEMESTER_START) |
|
while dt.weekday() != target_dow: |
|
dt += timedelta(days=1) |
|
return dt |
|
|
|
def main(): |
|
reader = csv.DictReader(sys.stdin) |
|
rows = [row for row in reader] |
|
cal = Calendar() |
|
for idx in ENABLED_COURSES: |
|
row = rows[idx-2] |
|
title = row.get("Курс","") |
|
teacher = row.get("Описание", "") |
|
schedule_raw = row.get("Расписание", "") |
|
links = row.get("Ссылки", "") |
|
desc = "\n".join(filter(None, [teacher, links])) |
|
for part in schedule_raw.split('\n'): |
|
time_info = parse_time(part) |
|
if not time_info: |
|
print(f"Skipping course: {title} - no time info") |
|
continue |
|
|
|
dow, start_tm, end_tm = time_info |
|
first_date = find_first_day(dow) |
|
dtstart = datetime.combine(first_date.date(), start_tm).replace(tzinfo=MSK) |
|
dtend = datetime.combine(first_date.date(), end_tm).replace(tzinfo=MSK) |
|
ev = Event() |
|
ev.add('summary', title) |
|
ev.add('description', desc) |
|
ev.add('dtstart', dtstart) |
|
ev.add('dtend', dtend) |
|
|
|
print(f"Adding course: {title}") |
|
|
|
until = datetime.fromisoformat(REPEAT_UNTIL).replace(tzinfo=MSK) |
|
ev.add('rrule', {'FREQ':'WEEKLY', 'UNTIL': until}) |
|
cal.add_component(ev) |
|
break |
|
with open("my_schedule.ics", "wb") as f: |
|
f.write(cal.to_ical()) |
|
|
|
if __name__ == "__main__": |
|
main() |