日历/事件 ICS 导出:使用 TZID=Europe/Berlin 导入 Outlook 时时间错误(+1 小时)

版本: Discourse 2026.1.5 (ESR),discourse-calendar 插件

摘要
使用设定的时区(timezone="Europe/Berlin"showLocalTime="true")创建的新事件,在下载 .ics 文件并导入 Outlook (Windows) 时,时间会显示错误,多出 1 小时。论坛本身显示的时间是正确的。仅受新事件影响,即通过 .ics 文件导入的情况。

复现步骤

  1. 创建一个事件(今天,处于夏令时 CEST/UTC+2):柏林时间下午 5:00 – 7:15。
[event start="2026-08-11 17:00" status="public" name="testevent 2" timezone="Europe/Berlin" showLocalTime="true" end="2026-08-11 19:15"]
[/event]

  1. 点击“添加到日历” → 下载 .ics 文件。
  2. 将文件导入 Outlook。

预期结果: 2026年8月11日,17:00 – 19:15
实际结果: 2026年8月11日,18:00 – 20:15(+1 小时)

ICS 内容(相关部分):

DTSTART;TZID=Europe/Berlin:20260811T170000
DTEND;TZID=Europe/Berlin:20260811T191500

(该文件不包含 Europe/BerlinVTIMEZONE 块。)

分析 / 疑似原因
导出功能使用 TZID=Europe/Berlin(IANA 名称)指定本地时间,而非使用 UTC(...Z)。Outlook 无法识别 IANA 时区名称(它使用 Windows 标识符,如“W. Europe Standard Time”),且在缺少 VTIMEZONE 定义的情况下,会回退到固定偏移量 UTC+1(CET/冬令时)。在夏令时期间(CEST = UTC+2),这会导致恰好 多出 1 小时。交叉验证:将同一文件导入 Google Calendar(原生支持 IANA 时区)显示正确的时间 17:00。

建议:ICS 导出应要么使用带 Z 的 UTC 时间戳,要么生成包含 DST 规则的完整 VTIMEZONE 块(另见关于 ICS 规范遵从性的讨论:LOCATION is not available in full ICS export)。

其他观察: 当同一事件在不带 timezone=/showLocalTime 的情况下创建时,导出的 .ics 使用 UTC,Outlook 显示 多出 2 小时(因为 17:00 UTC = 19:00 CEST)。这是文档中记录的 UTC 行为,但这进一步说明了 ICS 导出周围的时区处理对于期望看到本地时间的用户来说令人困惑。

作为对比,由于之前的日历时区行为,我一直将我的 Discourse 主机和应用容器运行在本地 IANA 时区,而不是 UTC。

我的主机设置为:

timedatectl set-timezone Europe/London

而我的 app.yml 包含:

- exec: ln -fs /usr/share/zoneinfo/Europe/London /etc/localtime
- exec: dpkg-reconfigure --frontend noninteractive tzdata

这意味着我的主机和 Discourse 容器都使用 Europe/London,包括自动的 GMT/BST 切换。

或许值得在你的安装环境中测试等效的 Europe/Berlin 设置,看看生成的 .ics 文件是否能正确导入到 Outlook 中:

timedatectl set-timezone Europe/Berlin

以及在 run: 部分中:

- exec: ln -fs /usr/share/zoneinfo/Europe/Berlin /etc/localtime
- exec: dpkg-reconfigure --frontend noninteractive tzdata

我想知道这是否会将你柏林时间 17:00 的事件从导入为 18:00 改为预期的 17:00。

如果确实如此,那就表明 Discourse/容器时区影响了导出;如果没有,则缺失的 VTIMEZONE/Outlook 处理可能独立于服务器时区。