Skip to content

Instantly share code, notes, and snippets.

@Olex1313
Created September 20, 2025 09:19
Show Gist options
  • Select an option

  • Save Olex1313/f21af94f26ae4c776e17b0fb62ced6c8 to your computer and use it in GitHub Desktop.

Select an option

Save Olex1313/f21af94f26ae4c776e17b0fb62ced6c8 to your computer and use it in GitHub Desktop.
povs course schedule

Собиратор расписания

Копия таблички - придется скачать файлик тк у нашего от кураторов кривая структура таблицы

Курсы указываются по номерам строк в табличке

ENABLED_COURSES = [
    2, 3, 4, # essential one
    9,  # algebra
    25, # gpu
    26  # mpp
]

Прогнать скрипт

python3 -m pip install icalendar # тут уж поставьте, лень самому формировать ical
cat ~/Downloads/mhs-copy.csv | python3 make_ical.py && open my_schedule.ics

Если в табличке нет расписания - курс не добавится в календарь, увы

Skipping course: Software Design - no time info
Adding course: IT-менеджмент
Adding course: Архитектура компьютера и операционные системы
Adding course: Вычислительная геометрия
Skipping course: Вычисления на видеокартах - no time info
Adding course: MPP
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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment