fix(时区): 日历口径收回东八区,读出的时刻统一成 ISO 并保留微秒
旧栈 Django 按 Asia/Shanghai 算日历,OJ2 重写时这个锚点丢了:容器和数据库会话 都是 UTC,于是「今日提交」在北京时间 0–8 点是空的,「凌晨/早起提交次数」整体偏 8 小时,热力图、AC 趋势年份、近两年活跃人数也各按进程时区切。 - 新增 apps/api/src/time.ts 作为唯一锚点(固定 +8 偏移,不依赖进程 TZ / tzdata), todayStart、成就小时/日期键、热力图、月份平移、年份夹逼全部改走它; SQL 里按日历切的一律显式 at time zone。 - db/index.ts:连接会话时区设为东八区(兜底);给 timestamptz(1184) 挂 parser, 读出统一成 ISO 8601 UTC,撤掉为拿 PG 文本形状写的 ::text。parser 保留微秒 —— 生产库 12.3 万条提交几乎全带微秒,截成毫秒会让翻页分界行和班级 AC 排名的 <= min(create_time) 把自己排除(翻页每页丢一条、排名少 1)。 - 前端 parseTime/zonedParts/zonedYear 按 Asia/Shanghai 渲染,n-date-picker 做 toPickerValue/fromPickerValue 平移,站内不再按浏览器时区取时间部件。 - Dockerfile 设 TZ=Asia/Shanghai 作为第二道兜底。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1d8B3f4SXJwDvUY625eQd
This commit is contained in:
@@ -160,7 +160,18 @@ COPY apps/api/src/db/meta/_journal.json /usr/local/share/oj2/migrations/meta/
|
||||
# 这不是审美问题:切换那天不用搬动任何文件,回滚时旧后端也立刻能找到自己的数据。
|
||||
# 少一次几十 GB 的 mv,就少一个在停机窗口里出错的机会。
|
||||
WORKDIR /data
|
||||
ENV TEST_CASE_DIRECTORY=/data/test_case \
|
||||
# TZ 是**兜底**,不是时区口径的依据 —— 业务时区的唯一锚点在 apps/api/src/time.ts。
|
||||
# 设它是为了任何一处还在用 `getHours()` / `setHours(0,0,0,0)` 这类跟进程时区走的代码
|
||||
# 也落在北京时间上(旧 Django 栈的 `settings.TIME_ZONE` 就是这个作用)。
|
||||
#
|
||||
# **必须同时设 worker 容器**:worker 跑的是同一个镜像、同样的 ENV,所以这一行两边都覆盖。
|
||||
# 本机 `bun run dev` 走不到这里,进程时区是开发机的 —— 这也是为什么 time.ts 用固定
|
||||
# 偏移而不是依赖进程 TZ:dev 和线上必须算得一样。
|
||||
#
|
||||
# debian:trixie-slim 自带 tzdata(实测 /usr/share/zoneinfo/Asia/Shanghai 存在),
|
||||
# 不用额外 apt 装。哪天换基底要重新确认这一条,否则 TZ 会被静默忽略、回落成 UTC。
|
||||
ENV TZ=Asia/Shanghai \
|
||||
TEST_CASE_DIRECTORY=/data/test_case \
|
||||
HITOKOTO_DIRECTORY=/data/hitokoto \
|
||||
UPLOAD_DIRECTORY=/data/public/upload \
|
||||
AVATAR_DIRECTORY=/data/public/avatar \
|
||||
|
||||
Reference in New Issue
Block a user