timetable
课表的数据类型 Course 和 Semester,以及处理课表的纯函数:解析周次、计算教学周、列出某天的课、判断上课状态和生成课前提醒的触发器。
这个模块描述课表数据,并提供一组处理课表的工具函数。如果你的插件要显示今天的课、判断现在是第几教学周,或者给某门课设置课前提醒,就会用到它。课表数据本身通过 services.timetable 获取。
源码:packages/sdk/src/timetable.ts。
星期沿用 JavaScript 的编号:0 = 周日 … 6 = 周六。
类型
type Course = {
id: string;
name: string;
location: string | null;
teacher: string | null;
weekday: number; // 0 = 周日 … 6 = 周六
start: string; // "HH:MM"
end: string; // "HH:MM"
/** 这门课上课的教学周;null 表示每周都上。 */
weeks: number[] | null;
/** 颜色标签在调色板中的序号(HostTheme.courseColor)。 */
color: number;
source: 'manual' | 'campus';
};
type Semester = { name: string; start: string /* "YYYY-MM-DD" */; weeks: number };函数
下面都是纯函数,有单元测试覆盖。
/**
* 解析周次表达式:"1-16"、"1-16单"、"2-16双"、"1,3,5-8"、"单周"、"双周"、"全部";也支持英文写法
* ("1-15 odd"、"2-16 even"、"odd weeks"、"every week")。null 表示每周。无法解析时抛出异常。
*/
function parseWeeks(expr: string, total?: number /* 20 */): number[] | null;
/** "1-16周"、"1-15单周"、"2,5,9周"(英文:"Weeks 1-16"、"Weeks 1-15 odd")。 */
function formatWeeks(weeks: number[] | null, locale?: 'zh-Hans' | 'en'): string;
/** 周次列表的等差规律(连续为步长 1,单双周为步长 2);没有规律时返回 null。 */
function weekPattern(weeks: number[]): { first: number; last: number; step: number } | null;
/** 某个日期所在的教学周(从 1 开始);没有学期信息时返回 null。 */
function weekOf(sem: Semester | null, date: Date): number | null;
/** 某个教学周里某个星期几对应的本地日期。 */
function dateOfWeek(sem: Semester, week: number, weekday: number): Date;
/** 某天要上的课,按开始时间排序。 */
function classesOn(courses: Course[], date: Date, sem: Semester | null): Course[];
/** 在当天的 `now` 时刻,这节课处于什么状态。 */
function classStatus(c: Course, now: Date): { state: 'before' | 'ongoing' | 'after'; progress: number; minutesToStart: number };
/**
* 每周一次的提醒触发器,在上课前 `minutesBefore` 分钟触发。有学期信息时,序列从第一个教学周持续到
* 最后一个教学周(单双周的步长为 2);没有学期信息时,从现在起每周触发。
*/
function courseReminderTrigger(c: Course, minutesBefore: number, sem: Semester | null, now?: number): Trigger;如果一门课的周次没有规律,courseReminderTrigger 会覆盖从第一周到最后一周的整段范围。
示例
const { courses, semester } = ctx.services.timetable.get();
const today = classesOn(courses, new Date(), semester);
const next = today.find((c) => classStatus(c, new Date()).state === 'before');
parseWeeks('1-15单'); // [1, 3, 5, …, 15]
formatWeeks([2, 4, 6, 8], 'en'); // "Weeks 2-8 even"