yml2213
65a4590291
refactor(time): 时间列统一走 UTCDateTime,并把 MySQL 会话时区对齐成 UTC
问题不是「UTC 还是本地时间」,而是这套口径有两个半吊子的地方:
1. 库里存 naive UTC、读出来也是裸时间,于是每一处比较/输出都得自己补时区。
项目里因此散了三份 _as_utc 和一堆 replace(tzinfo=UTC),P1a 排下一轮时间
时还炸过一次 TypeError: can't compare offset-naive and offset-aware。
2. MySQL 会话时区跟随系统 +08:00,而库里存的是 UTC —— SQL 里的 NOW()/
CURDATE() 比库里的时间快 8 小时,查询会静默返回空(P1a 排查时就遇到过,
看着像「没有数据」)。
改动:
- 新增 database.UTCDateTime:写时 aware→转 UTC 去 tzinfo、naive 视为 UTC;
读时一律补 UTC 时区。底层 DDL 仍是 DATETIME,**不需要迁移**。models.py 的
28 个时间列全部改用它,模型上的时间字段从此不再是裸值;
- docker-compose 给 mysql 加 --default-time-zone=+00:00,让 SQL 时间函数与存储
口径一致。安全性已核实:全库 0 个 TIMESTAMP 列、0 个 CURRENT_TIMESTAMP
默认值,改这里不会改变任何已有数据的语义;
- 新增 tests/test_utc_datetime.py:读出必须 aware、能直接和 datetime.now(UTC)
比较、带 +08:00 的写入要落成 UTC、naive 写入视为 UTC,并有一条元测试扫描
Base.metadata,防止以后新增时间列忘了用 UTCDateTime。
保留既有的 _as_utc 补丁(对 aware 值是幂等的,属防御性代码);新代码不再需要。
「存 UTC、算 UTC、显示本地」三条线至此各自明确:存储与比较统一 UTC,日志按
容器 TZ 显示本地时间,前端 formatTime 负责转本地。
2026-10-02 20:27:07 +08:00
..
2026-08-31 10:28:14 +08:00
2026-09-12 14:52:26 +08:00
2026-10-02 20:14:49 +08:00
2026-08-31 10:28:14 +08:00
2026-10-01 18:29:49 +08:00
2026-09-29 15:02:53 +08:00
2026-10-01 18:18:02 +08:00
2026-08-31 10:28:14 +08:00
2026-08-31 10:28:14 +08:00
2026-10-01 19:08:25 +08:00
2026-10-01 18:42:56 +08:00
2026-08-31 10:28:14 +08:00
2026-08-31 10:28:14 +08:00
2026-08-31 10:28:14 +08:00
2026-08-31 10:28:14 +08:00
2026-09-10 11:31:50 +08:00
2026-08-31 10:28:14 +08:00
2026-08-31 10:28:14 +08:00
2026-09-05 19:25:46 +08:00
2026-09-10 11:31:50 +08:00
2026-09-11 10:31:46 +08:00
2026-09-02 16:59:46 +08:00
2026-09-06 13:02:37 +08:00
2026-09-10 11:31:50 +08:00
2026-08-30 23:05:20 +08:00
2026-09-02 18:11:41 +08:00
2026-09-06 13:56:44 +08:00
2026-09-05 19:25:46 +08:00
2026-09-10 11:32:29 +08:00
2026-10-02 20:27:07 +08:00
2026-09-06 13:56:44 +08:00
2026-09-02 18:11:41 +08:00
2026-09-05 19:25:46 +08:00
2026-08-31 10:55:44 +08:00
2026-10-01 18:29:49 +08:00
2026-10-01 18:29:49 +08:00
2026-10-02 19:47:41 +08:00
2026-08-30 20:21:14 +08:00
2026-10-02 20:27:07 +08:00