Files
timeTableFix/docs/timezone.md
zikai cf941c50bc feat: 增加时区选择(自动检测,回退墨尔本)
顶栏新增时区选择器:加载时自动检测用户所在时区(Intl.DateTimeFormat),
检测不到则默认澳大利亚墨尔本。选定时区作为新建事件的默认 tzid 与下载
ICS 的 X-WR-TIMEZONE,不做时间换算(应用内部为 wall-clock 字符串)。

- 新增 src/lib/timezone.js(detect/list/validate/默认值)
- useCalendar 持 state.timezone、setTimezone、addEvent 传 tzid、serialize 注入 X-WR-TIMEZONE
- HeaderBar 顶栏下拉选择器 + i18n 文案
- 新增 test/timezone.test.js(15 项),全量 57 项通过
- README 简述功能,细节移至 docs/timezone.md
2026-07-27 09:49:13 +08:00

2.7 KiB
Raw Blame History

时区选择

timeTableFix 顶栏提供时区选择器。加载时自动检测用户所在时区,检测不到则默认 澳大利亚墨尔本(Australia/Melbourne

检测逻辑

src/lib/timezone.jsdetectTimezone()

  1. 读取 new Intl.DateTimeFormat().resolvedOptions().timeZone(浏览器/Node 标准 API
  2. 若抛错、返回空串或格式不合法,回退 DEFAULT_TIMEZONEAustralia/Melbourne)。

非安全上下文(无 https)或极旧环境可能拿不到时区,此时一律回退墨尔本。

下拉列表来源

listTimezones() = 精选常用 IANA 时区(COMMON_TIMEZONES,含墨尔本/上海/UTC 等)∪ 运行时 Intl.supportedValuesOf('timeZone')(若可用),去重后排序,UTC 置顶。旧浏览器不支持 supportedValuesOf 时静默降级为仅精选列表,保证下拉始终可用、无外部依赖。

作用范围(设计要点)

应用内部所有日期/时间均为 wall-clock 字符串YYYY-MM-DD + HH:MM,见 date.js不做任何时区换算。时区仅是一个挂在事件上的 IANA 标识(tzid),在 ICS 序列化/反序列化时作为 DTSTART/DTENDTZID 参数读写。

因此选定时区的作用是日历级默认值/标签,而非时间换算层:

行为 是否受选定时区影响
新建事件(「新增日程」)的 tzid 使用选定时区
下载 ICS 的 X-WR-TIMEZONE 写入选定时区
已导入事件的 tzid 保留原始 TZID不覆盖、不换算
日期/时间数值(编辑、预览、整理) 始终 wall-clock不换算
间隔去重(organize.js 不读 tzid,不受影响

为何不换算

  • 应用面向「整理/编辑日程文本」而非「跨时区会议调度」wall-clock 直观且无歧义。
  • organize.js[summary, location, 开始时间, 时长] 合并重复,引入换算会改变合并键、破坏既有 round-trip 测试。
  • 已导入事件保留原 TZID 保证 parse(serialize(parse(x))) 等价(见 ical-io.test.js round-trip 用例)。

实现位置

文件 改动
src/lib/timezone.js 新增:检测/列表/校验/默认值
src/composables/useCalendar.js state.timezone(初始 detectTimezone())、setTimezone()addEvent 传入 tzid、serialize 注入 X-WR-TIMEZONE
src/components/HeaderBar.vue 顶栏 <select> 选择器
src/i18n/locales/{zh-CN,en}.js header.timezone 文案

嵌入 mainPage

时区状态属于 timeTableFix 自有单例 store嵌入 mainPage 时随子模块独立运作,不与父项目共享。语言切换仍经 :locale prop 桥接(与时区无关)。