laoyang
8ae4e11507
修复同步后日程时间少 8 小时(服务器会删掉 DTSTART/DTEND 的 Z / TZID)
现象:客户端建的 10-16 08:00~17:00 同步到服务器后变成 00:00~09:00。
根因(2026-10-15 连服务器 family.yangyq.net 实测确认,不是 App 的解析 bug):
服务器会**直接删掉** DTSTART/DTEND 上的 `Z` 与 `TZID` 参数,**且不对数值做任何
时移**:
PUT DTSTART:20261020T060000Z -> 存回 DTSTART:20261020T060000
PUT DTSTART;TZID=Asia/Shanghai:20261020T140000 -> 存回 DTSTART:20261020T140000
于是"UTC 00:00"被当成"本地 00:00"。而本地 08:00 的正确 UTC 恰好就是 00:00,
所以症状正好是阅读端少 8 小时。
(DTSTAMP/CREATED/LAST-MODIFIED 是 RFC 规定的 UTC-only 属性,服务器反而保留 Z。)
交叉验证:全账号 2190 条事件里,计时事件(1163 条)的 DTSTART **无一例外都是
浮动本地时间**——带 Z 的 0 条、带 TZID 的 0 条。即该服务器的事实约定就是
"所有时间都是本地墙钟"。第三方客户端写的事件同样是浮动 DTSTART,且
DTSTART 浮动 + `UNTIL=...`(浮动)成对出现(例:研究生例会)。
改法:事件时间一律写**浮动本地时间**,与服务器约定对齐。
- IcsUtil.vevent:DTSTART/DTEND/RECURRENCE-ID/EXDATE 由 fmtUtc 改为 fmtLocal
(本地 getter、不带 Z)
- IcsUtil.fmtIcsTime:改为浮动本地(EXDATE / RECURRENCE-ID / UNTIL 共用)
- IcsUtil.rruleWithUntil:UNTIL 改为浮动本地
(RFC 5545:DTSTART 是本地时间时 UNTIL 必须也是本地时间,二者必须同形态)
- DTSTAMP 仍写 UTC+Z(RFC 规定),fmtUtcNow 不变
- 读取侧无需改动:parseTime / RruleUtil.parseUntil 已把"无 Z"按本地解析,
正好匹配浮动语义,往返一致
端到端验证(真服务器):
新写法 DTSTART:20261016T080000 -> 服务器原样存回 -> 读回仍为本地 08:00 ✅
数据修复:服务器上唯一一条受影响的日程(工作 / 项目评审 /
UID syncal-1792039765773-100047)已由 00:00~09:00 改回 08:00~17:00。
全账号仅此一条是本 App 创建的计时事件。
2026-10-15 18:45:51 +08:00
..
2026-10-15 18:45:51 +08:00
2026-09-13 15:50:37 +08:00
2026-09-13 15:50:37 +08:00
2026-09-13 15:50:37 +08:00
2026-09-13 15:50:37 +08:00