PostgreSQL 1991 年时间自动变成 +09:00
问题
开发时发现一个 1991 年出生用户的时间数据出现异常:
- 数据库:PostgreSQL
- 字段:
TIMESTAMP - 时区:
Asia/Shanghai - 预期:
UTC+08:00 - 实际:始终被解析成
UTC+09:00
一开始怀疑是 PostgreSQL、ORM 或程序时区配置错误,但实际原因是历史夏令时。
原因
Asia/Shanghai 并不代表“永远固定 UTC+8”。
它是 IANA 地区时区,会根据具体日期查询当时实际使用的时区规则。
中国曾在以下年份实行夏令时:
- 1986
- 1987
- 1988
- 1989
- 1990
- 1991
夏令时期间,中国标准时间会从:
UTC+08:00
变为:
UTC+09:00
因此,如果一个 1991 年的日期刚好落在当年的夏令时期间:
1991 日期 + Asia/Shanghai
就会正确地被解析成:
UTC+09:00
这不是 PostgreSQL 的 Bug,而是历史时区规则导致的正常结果。
避坑
不要把:
Asia/Shanghai
理解成:
固定 UTC+08:00
两者含义不同:
Asia/Shanghai:地区时区,会应用历史夏令时规则+08:00:固定 UTC Offset,不考虑历史规则
另外,生日本质上只是“日期”,通常不应该使用 TIMESTAMP。
推荐:
PostgreSQL DATE
而不是:
TIMESTAMP / TIMESTAMPTZ
一句话总结:
地区时区是历史规则,不是固定偏移;生日是日期,不是时间点。