日历文件读取
转换所有处理都在浏览器本地完成,数据不上传服务器
`.ics` 是日历通用的交换格式(RFC 5545),从 Google 日历、Outlook、Apple 日历导出的都是它。它的问题不是打不开,而是不好读:一个事件是一个 `BEGIN:VEVENT` 块,而你想要的「下周四下午三点、每周一次、到年底」分散在 `DTSTART`、`RRULE`、`UNTIL` 三个字段里,中间还夹着几十行 `VTIMEZONE` 定义。这个工具把它读成一张表。 ⚠️ 默认不做任何时区换算:带 `TZID` 的时间显示成文件里写的那个钟点,并把时区名标出来 —— 那是原始事实,换算是派生出来的,两者分别列出来才核对得了。 要换算的话,在选项里填一个 IANA 时区名(`Asia/Shanghai`、`America/New_York`、`UTC`),每个事件就会多一行「那个时刻在你选的时区里是几点」,并标出当天的 UTC 偏移。 ⚠️ 这一步不是拿一个固定偏移去减:偏移由平台自带的时区数据库算,所以是按事件那一天取的(纽约 1 月是 −05:00、7 月是 −04:00),历史上的规则变更也在里面。两种边界情况会被明确标出来:夏令时跳过的钟点在该时区不存在(不掰到邻近时刻),回拨重复的钟点对应两个时刻(取较早的那个并注明)。 ⚠️ 另外,「没有 `Z` 也没有时区名」的时间是浮动时间,意思是「谁看都是当地这个钟点」,跨时区发出去时每个人的本地时间都一样 —— 这与「某个确定的时刻」是两回事,这里会标出来。凡是这类时间,结果里都会附上说明。全部在浏览器本地完成。
功能
- 每个事件:摘要、开始与结束时间、时长、地点、描述(可选)、状态、UID
- 组织者与全部参与者(有 `CN` 显示名字,没有就显示地址)
- ⚠️ 重复规则读成一句人话:「每周(周四)共 4 次」,而不是 `FREQ=WEEKLY;BYDAY=TH;COUNT=4`
- ⚠️ 认不出的重复修饰符原样附在句尾 —— 不假装看懂了,因为那些条件恰恰决定某一次到底发生不发生
- 提醒数量(`VALARM` 子组件)
- 全天事件标出「全天」,时长按天算
- 汇总:事件数、带重复规则的、带提醒的、整体时间范围
- ⚠️ 正确处理 RFC 5545 的折行(一行上限 75 字节,续行以空格开头)—— 展开错了会在正文里凭空多出空格或把词断成两截
- ⚠️ 默认不做时区换算,只如实呈现文件里的钟点并标出时区名与「浮动时间」
- ⚠️ 可以按任意时区查看:填一个 IANA 时区名,每个事件多给一行换算后的钟点与当天的 UTC 偏移
- 偏移按事件那一天取,不是按今天 —— 跨夏令时的两个日期会给出不同的偏移
- 夏令时跳过的钟点(该时区不存在)与回拨重复的钟点(对应两个时刻)都会被明确标出,而不是悄悄掰到邻近的一个
- 换算那一行与「文件原样」那一行并存,原样那一行不被替换
- 全部在浏览器本地完成,文件不上传
使用方法
- 把 .ics 文件的全部内容粘进去(从 BEGIN:VCALENDAR 到 END:VCALENDAR)
- 需要看事件正文就勾上「一并输出事件的描述」
- 结果按事件分块列出,最后附上时区说明
常见问题
- 为什么不把时间换算成我所在时区?
- 因为正确换算需要该时区在那个具体日期上的偏移,而这不是一个固定值。夏令时规则改过很多次,有些国家改过好几次、有些取消了、有些时区的名称本身就有歧义。拿着 `Europe/London` 去查一个固定偏移,在夏令时生效的那几个月里就会错一小时 —— 而用户完全看不出来,只会按错的时间安排事情。所以这里显示文件里写的钟点并把时区名标出来:错的时间比没有时间更糟,而原始信息你随时可以自己对照。
- 「浮动时间」是什么?
- 不带宽带 `Z` 后缀、也没有时区名的时间,在 iCalendar 里的含义是「当地时间的这个钟点」—— 也就是说,这个事件在东京是 14:00,在伦敦也是 14:00,每个人的本地时间一样。它适用于「每天早上 7 点吃药」这类与地点无关的事。一旦把它当成某个确定的时刻去做换算,就会得出一个看似合理但其实错的结果。所以这里会把它标出来。
- 为什么不换算成我自己的时区?
- 默认不换算是故意的:文件里写的钟点与它的时区名是原始事实,换算是从那里派生出来的 —— 两者并排列出来,才核对得了换算对不对。要换算就在选项里填一个 IANA 时区名。⚠️ 而且那时也不是拿一个固定偏移去减:偏移由平台自带的时区数据库按事件那一天给出(夏令时规则改过很多次,不是一个固定值;给 `Europe/London` 套一个固定值,一年里有好几个月都差一小时)。被夏令时跳过或回拨重复的钟点会明确标出来,而不是悄悄掰到邻近的一个 —— 错的时间比没有时间更糟。
- 为什么有些重复规则的说法后面还跟着一串 `BY...=`?
- 因为那是没有读懂的修饰符,而它们往往正是决定某一次到底发生不发生的东西。比如 `BYDAY=-1FR`(每月最后一个周五)与 `BYSETPOS=-1`(取当月的最后一次)单独看都能认出来,组合起来的语义却需要完整的展开算法才能确定。这里只把认识的几个渲染成人话,剩下的原样附在句尾 —— 宁可让用户看到原始条件,也不要给一个看着通顺、却漏了关键限定的句子。
- 为什么描述里的文字有时候会粘在一起?
- 那多半说明文件是被别的工具改过的。RFC 5545 规定一行不超过 75 个字节,超出的部分要折到下一行、续行以一个空格开头;正确的展开是纯拼接、不加分隔符。有些工具在重新保存时按自己的规则换行,或者把折行处理成「加一个空格」,于是还原出来就多出了空格。这里按标准做,如果你看到的文本有异常的空格,来源是生成那个文件的一方。
- 能直接导出成 CSV 吗?
- 目前没有。结果可以整段复制,也可以逐行复制 —— 每一行的值单独可复制,方便贴进表格软件。真正要批量处理几十个日历文件的话,那已经超出浏览器里手工粘贴的范围了。
相关工具
时间戳转换
转换把 Unix 时间戳还原成日期时间,或反过来。秒 / 毫秒 / 微秒 / 纳秒自动识别,支持小数、负数与 Windows FILETIME。全部在浏览器本地完成。
日期计算
转换算两个日期之间相差多少天,或给一个日期加减若干天、周、月。日期用日历挑或直接粘贴,结束日期留空就与今天比较。全部在浏览器本地完成。
二维码
生成器把文本、链接、WiFi 配置、名片、日历事件生成二维码,前景与背景色可调,可下载 PNG 或矢量 SVG。编码全程在浏览器本地完成。
进制转换
转换在二、八、十、十六、36、64 进制之间互转,六种结果一次全部给出,19 位的雪花 ID 也能一位不差。全部在浏览器本地完成。
Cron 解析
转换把 cron 表达式逐字段讲成人话,算出接下来几次与上一次的执行时间;永远不会触发的表达式会当场说明原因。全部在浏览器本地解析。
颜色转换
转换在 HEX、RGB、HSL、HWB、CMYK 与 OKLab、OKLCH、Lab、XYZ 之间互转,另给出色温、反色、互补色、最接近的 ANSI 终端色与 WCAG 对比度。全部在浏览器本地完成。