Skip to content

Instantly share code, notes, and snippets.

@chuangzhu
Last active September 19, 2023 19:39
Show Gist options
  • Save chuangzhu/f9b78ea3d7718fd96626e4dece2f1652 to your computer and use it in GitHub Desktop.
Save chuangzhu/f9b78ea3d7718fd96626e4dece2f1652 to your computer and use it in GitHub Desktop.
Convert DGUT courses table to iCalendar
#!/usr/bin/env python3
# SPDX-License-Identifier: AGPL-3.0
# Convert courses table from https://jw.dgut.edu.cn → 学生服务→ 网上选课→ 选课结果 to iCalendar
# Usage: copy the query result to a spreadsheet application, export it as CSV, then run:
# ./dgutcourses2ics.py 2023-09-04 < courses.csv > courses.ics
# ^ first monday of the semester
import csv
import sys
from datetime import datetime, date, time, timedelta
from textwrap import dedent
import uuid
import re
# https://jwdy.dgut.edu.cn/zxsj/
SCHEDULE = [[time(8, 30), time(9, 15)],
[time(9, 25), time(10, 10)],
[time(0, 25), time(11, 10)],
[time(1, 15), time(12, 0)],
[time(4, 30), time(15, 15)],
[time(5, 25), time(16, 10)],
[time(6, 25), time(17, 10)],
[time(7, 20), time(18, 5)],
[time(9, 30), time(20, 15)],
[time(0, 25), time(21, 10)],
[time(1, 15), time(22, 0)]]
DAYS = '一二三四五六日'
mon1 = date.fromisoformat(sys.argv[1])
reader = list(csv.reader(sys.stdin))
print('BEGIN:VCALENDAR')
print('PRODID:-//Chuang Zhu//dgutcourses2ics.py//EN')
print('VERSION:2.0')
for i, row in enumerate(reader):
课程, 学分, 课程类别, 任课老师, 上课班号, 上课班级名称, 选课方式, 选课状态, 已选免听, 限选人数, 可选人数, 上课时间上课地点 = row
周次上课时间, 上课地点 = 上课时间上课地点.split()
周次, 上课时间 = 周次上课时间[1:].split(']', 1)
上课时间 = 上课时间.replace('[', '(').replace(']', ')')
# 课程, 学分, 总学时, 课程类别, 承担单位, 上课班号, 上课班组, 限选人数, 已选免听, 可选人数, 周次, 授课方式, 任课老师, 上课时间, 上课地点 = row
# if not 课程:
# 课程, 学分, 总学时, 课程类别, 承担单位, 上课班号, 上课班组, 限选人数, 已选免听, 可选人数 = reader[i-1][:10]
for recur in 周次.split(','): # 2,4-12
m = re.match(r'周(\S)\((\d+)-(\d+)节\)', 上课时间) # 周五(1-2节)
weekday = DAYS.find(m.group(1))
starttime = SCHEDULE[int(m.group(2)) - 1][0]
endtime = SCHEDULE[int(m.group(3)) - 1][1]
if '-' in recur:
startweek, endweek = map(int, recur.split('-'))
count = endweek - startweek + 1
else:
startweek = int(recur)
count = 1
startdate = mon1 + timedelta((startweek-1)*7+weekday)
start = datetime.combine(startdate, starttime)
end = datetime.combine(startdate, endtime)
description = '\\n'.join([f'课程: {课程}',
f'学分: {学分}',
# f'总学时: {总学时}',
f'课程类别: {课程类别}',
# f'承担单位: {承担单位}',
f'上课班号: {上课班号}',
# f'上课班组: {上课班组}',
f'限选人数: {限选人数}',
f'已选免听: {已选免听}',
f'可选人数: {可选人数}',
f'周次: {周次}',
# f'授课方式: {授课方式}',
f'任课老师: {任课老师}',
f'上课时间: {上课时间}',
f'上课地点: {上课地点}'])
event = f"""
BEGIN:VEVENT
DTSTAMP:{datetime.utcnow().strftime('%Y%m%dT%H%M%S')}Z
DTSTART;TZID=Asia/Shanghai:{start.strftime('%Y%m%dT%H%M%S')}
DTEND;TZID=Asia/Shanghai:{end.strftime('%Y%m%dT%H%M%S')}
UID:{uuid.uuid4()}
SUMMARY:{课程}
LOCATION:{上课地点}
RRULE:FREQ=WEEKLY;COUNT={count}
SEQUENCE:0
DESCRIPTION:{description}
END:VEVENT
"""
print(dedent(event).strip())
print('END:VCALENDAR')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment