iCalendar (ICS) 的养成方式

介绍

iCalendar 是 RFC 5545 定义的通用日历数据交换标准(下称「ICS 协议」),可以通过 WebDAV / SyncML / HTTP 等方式进行传输。说人话就是,可以直接在日历 app 导入 .ics 文件或订阅源来增加(或删除)日历。

当然,很多日历 app 在联网后都能获取一些常见的节气和节假日数据,如果局限于此,可能会觉得 ICS 协议也没什么稀奇的,但这只是实际应用层的冰山一角,深入挖掘后可以了解到各种奇怪的用法。加之 ICS 格式本身很简单,手搓一个应用也是分分钟的事。

订阅源

  • 节假日、调休、补班日历
    • 整理自中国政府网,自动维护,支持定制化
    • 节假日很多日历都有,但调休和补班就不一定了,在万恶的调休制度取消之前这个功能很实用
  • 二十四节气
    • 2015 年到 2050 年的节气,由于清明放假,通常会作为节假日包含在其他订阅中,所以实际上订阅源只有二十三节气
    • 项目基于 lunar-calendar,后者的数据源来自香港天文台,覆盖 1901 年到 2100 年间两百年的农历 - 公历对照表,自带 3 年数据,也支持生成 200 年间任意时间段的数据,注意由于算法原因 2057 年会出现错位
  • Steam 愿望单
    • 根据游戏发售日生成日历,用来追新游戏是极好的
    • 在 repo secret 设置 STEAMUID 即可由 GitHub Action 自动维护
    • Steam_ID 可以在 SteamDB 的 Steam Calculator 界面查看
  • VNDB 新游戏发售日历
    • 我参考上面的 SteamWishlistCalendar 制作的 VNDB-Calendar
    • 原理相同,只不过使用的是 VNDB API,同样由 GitHub Action 自动维护
    • 除了新游戏,还提供民间汉化补丁的发布日历,通过自定义参数可以实现更多效果
  • CnGal 游戏发售日历
    • 同上,数据源从 VNDB 替换为 CnGal,由于 CnGal 包含的数据量偏少,其实意义不大
  • Firefox Release Calendar
    • 火狐浏览器更新日历,同理,其实很多程序更新也能转换成日历,但是这类更新太多,一般建议用 RSS 批量检查更新,或者包管理器一条龙
  • 课表
    • 支持自定义课程周数和其他信息,支持定义教室 GPS 等信息
    • 初始配置比较麻烦,可能需要写个 Python 爬虫手动清洗一下教务处数据,然后再录入,但时间表和教室信息之类的后续可以复用这么想心理就平衡了
    • 虽然现在用不到,但说不定哪天就财富自由 + 想不开去多读几个本硕博了

实际应用远远不止这些,常规点像 🐶 都不用的 Facebook、SpaceX 火箭发射也有订阅源,电视剧、演唱会之类的更不用说,还有很多奇怪的例子,比如 Sky Sports 提供的体育赛事日历LPL & LCK 赛程,Epic 每周免费游戏等等……

当然,对时间不敏感的内容也可以考虑用 RSSHub 生成 RSS,然后通过一系列过滤规则来排除不必要的信息,RSS 展开可以讲很久,有缘再写一篇介绍。

另有随手搓的 rss2ics,可以将 RSS 转换成 ICS。

App

因人而异,这里只简单提几句我的选择。

手机上的日历算是两极分化最严重的 app,下限极低,上限极高:

  • 不用的人从来不需要,需要的人天天都会打开
  • 可以是简单的节假日日历,也可以搞得相当复杂,从早到晚精确到分钟
  • 可以只包括单纯的信息,也可以和工作、社交、影音、娱乐 app 联动

Android 通过 ICSx⁵(只支持单向同步,需要双向同步可以用 DAVx⁵)订阅 ICS 并同步到日历,将「订阅获取」与「日历查看」分离,摆脱日历 app 的捆绑,还可以避免 app 联网导致日历泄漏,目前在用 Fossify Calendar,至于连日历导出功能都不肯做,却强制要求联网和访问联系人的垃圾 OEM 日历,不用也罢。

桌面端我更喜欢 TUI ,私密日历用 calcurse,订阅源的查看和获取则使用 khal 和基于 Cloudflare Python Worker 的 URL redirector,比配置 Radicale 方便,也灵活得多。

很冗长
-wcurl https://raw.githubusercontent.com/lanceliao/china-holiday-calender/master/holidayCal.ics
-wcurl https://raw.githubusercontent.com/KaitoHH/24-jieqi-ics/master/23_solar_terms_2015-01-01_2050-12-31.ics
更优雅
+wcurl https://ics.vinfall.com/{holiday,jieqi}
+for i in holiday jieqi; do mv $i $i.ics; done

管理

因为 Steam/VNDB/CnGal 事件很多,我更习惯在周末扫一眼未来一周的新发售游戏,避免信息过载。

khal 采用别扭的 vdir 格式,每个 ics 文件只能包含一个 event,用起来非常折磨。 因为私密日历存在 calcurse,解决方案简单粗暴:手动更新 ics -> 删除 khal 数据 -> 重新导入。

# update iCalendar
cd ~/.local/share/khal/calendars/remote/
wcurl https://ics.vinfall.com/{cngal,vndb,steam}
for i in cngal vndb steam; do mv $i $i.ics; done
# nuke khal data
cd ~/.local/share/khal
rm -f khal.db calendars/imported/*
# import ics into khal
cd calendars/remote/
khal import --batch *.ics
khal interactive

延伸

上个月修复 Hugo /posts 未按照 lastmod 倒序的问题时,顺带加了按照发布时间倒序的 /archive,现在可以在两种排序之间任意切换。在此期间发现 Hugo 支持 输出自定义格式,其中就包括 iCalendar,记录在 Add ICS Output to Hugo Blog

Vinfall's Geekademy

Sine īrā et studiō