曾神在群里分享了一个开源项目 《JMU-json2ics》 。可以用我们学校的课表生成 ics日历 文件。
这个小项目引发了我的兴趣,遂决定阅读一遍源码,顺便复习下python语法。
第一部分:json文件结构解读
总体结构
课程信息主要保存在 ”adminclass“ 条录下
{ "studentTableVm": { "id": 22471, "name": "陈煜晗", //学生姓名 "code": "2020*****104",//学生学号 "grade": "2020", //年级 "department": "计算机工程学院", //学院 "major": "计算机科学与技术", //专业 "adminclass": "计算2014",//班级 "credits": 25.75, //学分 "totalRetakeCredits": 0, //已确认学分 "activities": [...], //!!!课程列表!!!。 "lessonSearchVms": [...],//下列不表。 "practiceLessonSearchVms": [...], "arrangedLessonSearchVms":[...], "timetableLayout": {"id": 1...}, "courseTablePrintConfigs": [...], "lessonNamePrint": false }} 课程信息 activities
以列表形式保存课程信息。
对于每一个课程,以字典形式保存基本信息
{ "lessonId": 62937, //课程代号? "lessonCode": "D000607-0006",//课程编号 "lessonName": "21-22-01大学英语三级综合06", //课程班名称 "courseCode": "D000607", "courseName": "大学英语 (3)", //课程名称 "weeksStr": "5~13(单)", //上课周次描述信息 "weekIndexes": [5, 7, 9, 11, 13],//上课周次 "room": "汉水0306",//教室 "building": "庄汉水楼",//教学楼 "campus": "主校区",//教学校区 "weekday": 1,//周几上课 "startUnit": 7,//第几节课开始 "endUnit": 8,//第几节课结束 "lessonRemark": null,//重修 "teachers": ["林瑞芳"],//授课教师 "courseType": null,//课程类型 默认? "credits": 2.5,//学分 "periodInfo": {"total": 40...},//进阶信息,下表。 "stdCount": 66,//学生人数 "limitCount": 80,//限制人数 "tableShowAdminclass": [...], "adminclassVms": [...], "activityRoomTypeSign": null, "activityRoomTimesOrUnits": null, "taskPeopleNum": null}, ”periodInfo“ 是课程的进阶信息。 这里没有用到,仅作猜测,不保证正确性。
"periodInfo": { "total": 40, "weeks": 16, "theory": 40,//课时 "theoryUnit": "HOUR",//课时单位 "requireTheory": 40,//要求课时 "practice": null, //实践课时 "practiceUnit": null,//实践课时单位 "requirePractice": null,//需要实践课时 "focusPractice": null,//需要实践课时单位 "focusPracticeUnit": null, "dispersedPractice": null, "test": null,//小测 "testUnit": null,//小测单位 "requireTest": null,//要求小测 "experiment": null,//实验课时 "experimentUnit": null,//实验课时单位 "requireExperiment": null,//要求实验课时 "machine": null,//机器 "machineUnit": null,//机器单位 "requireMachine": null,//需要机器单位 (上机?) "design": null,//课程设计课时 "designUnit": null,//课程设计课时单位 "requireDesign": null,//要求课程设计课时 "periodsPerWeek": 0, //每周周期 "extra": null,//额外课时 "extraUnit": null,//额外课时单位 "requireExtra": null//要求额外课时 }, 第二部分 :《JMU-json2ics》源码解读
主程序
def getInformation(json_data): return json_data["studentTableVm"]["name"], json_data["studentTableVm"]["id"], json_data["studentTableVm"]["grade"], json_data["studentTableVm"]["major"], json_data["studentTableVm"]["adminclass"]def main(): first_day_date_str = '2021-09-06' #开学日期。 time_zone = pytz.timezone('Asia/Shanghai') #更改时区为亚洲/上海 # 保存日历信息, Calendar 是常见的日历类。 calendar = Calendar() #以UTF-8编码打开json文件。 with open('data1.json', encoding='utf-8') as f: #读取json文件信息,以字典形式保存在json_data中 json_data = json.load(f) #依次获取 姓名、学号、年级、专业、班级 name, studentId, grade, major, class_name = getInformation(json_data) #读取课程列表 courseList = json_data["studentTableVm"]["activities"] for course in courseList:... #(下接) 遍历课程
get_course_take_time
# 返回上课时间def get_course_take_time(course_time): # 第1、2节课8:0:0 - 9:35:0 以此类推。 course_time_table = {'12': [[8, 0, 0], [9, 35, 0]], '34': [[10, 5, 0], [11, 40, 0]], '14': [[8, 0, 0], [11, 40, 0]], '56': [[14, 0, 0], [15, 35, 0]], '78': [[15, 55, 0], [17, 30, 0]], '58': [[14, 0, 0], [17, 30, 0]], '910': [[19, 0, 0], [20, 35, 0]], '911': [[19, 0, 0], [21, 25, 0]]} return course_time_table[course_time][0], course_time_table[course_time][1] for course in courseList: # 课程在星期几 course_in_day_of_week = int(course['weekday']) # 课程在第几周(列表形式) course_take_weeks = list(course['weekIndexes']) # 课程开始时间、结束时间 course_begin_time, course_end_time = get_course_take_time( "{}{}".format(course['startUnit'], course['endUnit'])) # 遍历上课周次 for week in course_take_weeks:...#(下接) #生成 (class_name)-(name).ics文件 output_file_name = '{} - {}.ics'.format(class_name, name) output_file = open(output_file_name, 'wb') #将calendar中的信息写入文件 output_file.write(calendar.to_ical()) output_file.close() 遍历课程的每一个周次
get_course_date
# 返回上课的日期def get_course_date(first_day_date_str, course_in_day_of_week, which_week): first_day_date = datetime.datetime.strptime( first_day_date_str, r'%Y-%m-%d') return first_day_date + datetime.timedelta(days=(which_week - 1) * 7 + (course_in_day_of_week - 1))
for week in course_take_weeks: course_date = get_course_date(first_day_date_str, course_in_day_of_week, week) # 注意这是icalendar中的Event # 创建一个事件(课程) event = Event() # 添加课程概述,这里只添加了课程名称 event.add('summary', course['courseName']) #添加课程开始时间 event.add('dtstart', datetime.datetime(course_date.year, course_date.month, course_date.day, course_begin_time[0], course_begin_time[1], course_begin_time[2], tzinfo=time_zone)) #添加课程结束时间 event.add('dtend', datetime.datetime(course_date.year, course_date.month, course_date.day, course_end_time[0], course_end_time[1], course_end_time[2], tzinfo=time_zone)) #添加触发事件时间 event.add('dtstamp', datetime.datetime(course_date.year, course_date.month, course_date.day, course_begin_time[0], course_begin_time[1], course_begin_time[2], tzinfo=time_zone)) # 添加课程地点 event.add('location', course['room']) # 将事件添加到日历中 calendar.add_component(event) 完整源码及项目地址
源码
# -*- coding:utf-8 -*-import requestsfrom icalendar import Calendar, Eventimport pytzimport datetimeimport hashlibimport osimport re# 支持jsonimport json# 返回上课的日期def get_course_date(first_day_date_str, course_in_day_of_week, which_week): first_day_date = datetime.datetime.strptime( first_day_date_str, r'%Y-%m-%d') return first_day_date + datetime.timedelta(days=(which_week - 1) * 7 + (course_in_day_of_week - 1))# 返回上课时间def get_course_take_time(course_time): # 第1、2节课8:0:0 - 9:35:0 以此类推。 course_time_table = {'12': [[8, 0, 0], [9, 35, 0]], '34': [[10, 5, 0], [11, 40, 0]], '14': [[8, 0, 0], [11, 40, 0]], '56': [[14, 0, 0], [15, 35, 0]], '78': [[15, 55, 0], [17, 30, 0]], '58': [[14, 0, 0], [17, 30, 0]], '910': [[19, 0, 0], [20, 35, 0]], '911': [[19, 0, 0], [21, 25, 0]]} return course_time_table[course_time][0], course_time_table[course_time][1]def getInformation(json_data): return json_data["studentTableVm"]["name"], json_data["studentTableVm"]["id"], json_data["studentTableVm"]["grade"], json_data["studentTableVm"]["major"], json_data["studentTableVm"]["adminclass"]def main(): first_day_date_str = '2021-09-06' time_zone = pytz.timezone('Asia/Shanghai') # 保存日历信息 calendar = Calendar() # 初始化? calendar.add('prodid', '-//My calendar product//mxm.dk//') calendar.add('version', '2.0') with open('data1.json', encoding='utf-8') as f: json_data = json.load(f) name, studentId, grade, major, class_name = getInformation(json_data) courseList = json_data["studentTableVm"]["activities"] print(type(courseList)) for course in courseList: # 课程在星期几 course_in_day_of_week = int(course['weekday']) # 课程在第几周(列表形式) course_take_weeks = list(course['weekIndexes']) # 课程开始时间、结束时间 course_begin_time, course_end_time = get_course_take_time( "{}{}".format(course['startUnit'], course['endUnit'])) # 遍历上课周次 for week in course_take_weeks: course_date = get_course_date(first_day_date_str, course_in_day_of_week, week) event = Event() event.add('summary', course['courseName']) event.add('dtstart', datetime.datetime(course_date.year, course_date.month, course_date.day, course_begin_time[0], course_begin_time[1], course_begin_time[2], tzinfo=time_zone)) event.add('dtend', datetime.datetime(course_date.year, course_date.month, course_date.day, course_end_time[0], course_end_time[1], course_end_time[2], tzinfo=time_zone)) event.add('dtstamp', datetime.datetime(course_date.year, course_date.month, course_date.day, course_begin_time[0], course_begin_time[1], course_begin_time[2], tzinfo=time_zone)) event.add('location', course['room']) calendar.add_component(event) output_file_name = '{} - {}.ics'.format(class_name, name) output_file = open(output_file_name, 'wb') output_file.write(calendar.to_ical()) output_file.close()if __name__ == '__main__': main() 项目地址
tiny / JMU-json2ics



