Last active
February 25, 2019 14:56
-
-
Save ysc3839/b52137fda3181a61a1c87bd6ff39fbb5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- encoding: utf-8 -*- | |
import json, uuid, os, datetime | |
from datetime import time as tm | |
from functools import partial | |
open_utf8 = partial(open, encoding='utf-8') | |
ICAL_HEADER = r'''BEGIN:VCALENDAR | |
PRODID:-//ysc3839//classlist-to-ical.py// | |
VERSION:0.1 | |
CALSCALE:GREGORIAN | |
METHOD:PUBLISH | |
BEGIN:VTIMEZONE | |
TZID:Asia/Shanghai | |
BEGIN:STANDARD | |
TZOFFSETFROM:+0800 | |
TZOFFSETTO:+0800 | |
TZNAME:CST | |
DTSTART:19700101T000000 | |
END:STANDARD | |
END:VTIMEZONE | |
''' | |
ICAL_VEVENT = r'''BEGIN:VEVENT | |
DTSTART;TZID=Asia/Shanghai:{DTSTART} | |
DTEND;TZID=Asia/Shanghai:{DTEND} | |
RRULE:FREQ=WEEKLY;COUNT={RCOUNT};BYDAY={RDAY} | |
DTSTAMP:{DTSTAMP} | |
UID:Ical{UID} | |
CREATED:{DTSTAMP} | |
DESCRIPTION:{DESC} | |
LAST-MODIFIED:{DTSTAMP} | |
LOCATION:{LOC} | |
SEQUENCE:0 | |
STATUS:CONFIRMED | |
SUMMARY:{SUMMARY} | |
TRANSP:{TRANSP} | |
END:VEVENT | |
''' | |
ICAL_FOOTER = r'''END:VCALENDAR | |
''' | |
DATE_START = datetime.date(2019, 2, 25) | |
CLASS_TIMES = [ | |
None, #0 None | |
# Morning | |
(tm(8, 30), tm(9, 15)), # 1 08:30-09:15 | |
(tm(9, 20), tm(10, 5)), # 2 09:20-10:05 | |
(tm(10, 25), tm(11, 10)), # 3 10:25-11:10 | |
(tm(11, 15), tm(12, 00)), # 4 11:15-12:00 | |
# Afternoon | |
(tm(13, 50), tm(14, 35)), # 5 13:50-14:35 | |
(tm(14, 40), tm(15, 25)), # 6 14:40-15:25 | |
(tm(15, 45), tm(16, 30)), # 7 15:45-16:30 | |
(tm(16, 35), tm(17, 20)), # 8 16:35-17:20 | |
# Night | |
(tm(18, 20), tm(19, 5)), # 9 18:20-19:05 | |
(tm(19, 10), tm(19, 55)), # 10 19:10-19:55 | |
(tm(20, 0), tm(20, 45)), # 11 20:00-20:45 | |
] | |
WEEK_DAYS = [ | |
None, | |
'MO', | |
'TU', | |
'WE', | |
'TH', | |
'FR', | |
'SA', | |
'SU' | |
] | |
def dt_to_str(dt): | |
return "%04d%02d%02dT%02d%02d%02d" % ( | |
dt.year, | |
dt.month, | |
dt.day, | |
dt.hour, | |
dt.minute, | |
dt.second | |
) | |
def main(): | |
with open_utf8('classlist.json', 'r') as f: | |
classlist = json.load(f) | |
with open_utf8('out.ics', 'w', newline='\r\n') as f: | |
f.write(ICAL_HEADER) | |
xsbjList = {} | |
for xsbj in classlist['xsbjList']: | |
xsbjList[xsbj['xslxbj']] = xsbj['xsmc'] | |
utcnow_str = dt_to_str(datetime.datetime.utcnow()) + 'Z' | |
kbList = classlist['kbList'] | |
for kb in kbList: | |
if kb['sxbj'] != '1': # =='1':已选上, else:待筛选 | |
continue | |
kb['xsmc'] = xsbjList[kb['xslxbj']] if 'xslxbj' in kb else '' | |
if 'zcmc'in kb: | |
kb['zcmc'] = kb['zcmc'].replace('(', '(').replace(')', ')') | |
week_range = kb['zcd'].rstrip('周').split('-') | |
week_range = [int(_) for _ in week_range] | |
weekday = int(kb['xqj']) | |
weeks = week_range[1] - week_range[0] + 1 if len(week_range) == 2 else 1 | |
start_date = DATE_START + datetime.timedelta(days=weekday-1, weeks=week_range[0]-1) | |
class_range = kb['jcs'].split('-') | |
class_range = [int(_) for _ in class_range] | |
start_time = CLASS_TIMES[class_range[0]][0] | |
end_time = CLASS_TIMES[class_range[1]][1] | |
event_data = {} | |
event_data['DTSTART'] = dt_to_str(datetime.datetime.combine(start_date, start_time)) | |
event_data['DTEND'] = dt_to_str(datetime.datetime.combine(start_date, end_time)) | |
event_data['RCOUNT'] = weeks | |
event_data['RDAY'] = WEEK_DAYS[weekday] | |
event_data['DTSTAMP'] = utcnow_str | |
event_data['UID'] = uuid.uuid4().hex | |
event_data['DESC'] = r'''周: {zcd} | |
教师: {xm}{0} | |
考察方式: {khfsmc} | |
课程性质: {xsmc} | |
教学班名称: {jxbmc}'''.format('' if 'zcmc' not in kb else ' (%s)' % kb['zcmc'], **kb).replace('\n', '\\n') | |
event_data['LOC'] = kb['cdmc'] | |
event_data['SUMMARY'] = kb['kcmc'] | |
event_data['TRANSP'] = 'OPAQUE' | |
f.write(ICAL_VEVENT.format(**event_data)) | |
if week_range[0] != 1: | |
start_date = DATE_START + datetime.timedelta(days=weekday-1) | |
event_data['DTSTART'] = dt_to_str(datetime.datetime.combine(start_date, start_time)) | |
event_data['DTEND'] = dt_to_str(datetime.datetime.combine(start_date, end_time)) | |
event_data['RCOUNT'] = week_range[0] - 1 | |
event_data['UID'] = uuid.uuid4().hex | |
event_data['SUMMARY'] = '!!!' + event_data['SUMMARY'] | |
event_data['TRANSP'] = 'TRANSPARENT' | |
f.write(ICAL_VEVENT.format(**event_data)) | |
f.write(ICAL_FOOTER) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment