You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5.8 KiB
5.8 KiB
Folder Service 时间戳规范修正
日期:2026-01-29
类型:规范修正(重大)
影响范围:folder-service.md文档
修正背景
在 v3.5 版本中,错误地将所有事件时间字段从 TIMESTAMPTZ 改为 TIMESTAMP WITHOUT TIME ZONE,这违反了 PostgreSQL 最佳实践和项目架构决策(ADR 006)。
本次修正(v3.6)将时间戳规范改回正确的 TIMESTAMPTZ。
修正内容
1. 时间戳类型修正(符合 ADR 006)
v3.5(错误):
-- ❌ 错误:使用 TIMESTAMP WITHOUT TIME ZONE 记录事件时间
created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP WITHOUT TIME ZONE,
v3.6(正确):
-- ✅ 正确:使用 TIMESTAMPTZ 记录事件时间
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deleted_at TIMESTAMPTZ,
涉及表:
folders表:created_at,updated_at,deleted_atfolder_members表:joined_at,created_atfolder_shares表:expires_at,created_at,revoked_atfolder_export_jobs表:created_at,started_at,completed_at,expires_at
2. 默认值修正
v3.5(错误):
DEFAULT CURRENT_TIMESTAMP
v3.6(正确):
DEFAULT now()
原因:
now()是 PostgreSQL 推荐的函数- 与
TIMESTAMPTZ类型配合使用 - 更简洁明确
3. 字段注释修正
v3.5(错误):
COMMENT ON COLUMN folders.created_at IS '创建时间(UTC)';
v3.6(正确):
COMMENT ON COLUMN folders.created_at IS '创建时间(自动记录时区)';
原因:
TIMESTAMPTZ自动记录时区信息- 不应标注"UTC",因为数据库会自动处理时区转换
- 更准确地描述字段行为
修正理由
根据 ADR 006: 事件时间戳必须使用 TIMESTAMPTZ:
1. 语义正确性
事件时间(created_at, updated_at, deleted_at 等)表示真实世界发生的时间点,必须包含时区信息。
错误理解:应用层使用 UTC,所以数据库不需要时区
正确理解:事件时间是绝对时间点,必须用 TIMESTAMPTZ 表示
2. PostgreSQL 官方推荐
PostgreSQL 官方文档明确推荐:
- 使用
TIMESTAMPTZ记录事件时间 - 数据库自动处理时区转换
- 避免应用层时区处理错误
3. 性能相同
TIMESTAMPTZ 与 TIMESTAMP WITHOUT TIME ZONE:
- 存储大小完全相同(8 字节)
- 查询性能完全相同
- 索引性能完全相同
4. 多时区支持
使用 TIMESTAMPTZ 的优势:
- 支持全球化部署
- 支持多时区用户
- 数据库自动处理时区转换
- 避免应用层时区错误
5. 数据一致性
-- TIMESTAMPTZ 自动处理时区
SET timezone = 'Asia/Shanghai';
SELECT created_at FROM folders WHERE id = '...';
-- 返回:2026-01-29 18:00:00+08
SET timezone = 'America/New_York';
SELECT created_at FROM folders WHERE id = '...';
-- 返回:2026-01-29 05:00:00-05
-- 同一时间点,不同时区显示
文档版本更新
v3.6 (2026-01-29) - 当前版本
- ✅ 修正时间戳规范(符合 ADR 006):
- 数据库层:所有事件时间字段使用
TIMESTAMPTZ - 默认值:统一使用
now()而非CURRENT_TIMESTAMP - 字段注释:改为"自动记录时区"而非"UTC"
- 理由:事件时间表示真实世界时间点,必须包含时区信息
- 数据库层:所有事件时间字段使用
v3.5 (2026-01-29) - 已废弃
- ❌ 错误的时间戳规范(已被 v3.6 修正):
- 错误地使用
TIMESTAMP WITHOUT TIME ZONE记录事件时间 - 违反了 PostgreSQL 最佳实践和 ADR 006 决策
- 错误地使用
技术栈规范更新
同时更新了 jointo-tech-stack skill 的时区规范:
database.md 修正
-- ❌ v3.5 错误示例
created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- ✅ v3.6 正确示例
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
backend.md 修正
核心原则:
- 数据库使用
TIMESTAMPTZ记录事件时间 - Python 应用层使用
datetime.now(timezone.utc)生成 UTC 时间 - PostgreSQL 自动处理时区转换
影响评估
文档层面
- ✅ 文档符合 PostgreSQL 最佳实践
- ✅ 文档符合 ADR 006 架构决策
- ✅ 示例代码正确可用
实现层面
- ⚠️ 如果已按 v3.5 实现,需要修正
- ⚠️ 检查所有时间戳列类型
- ⚠️ 检查默认值定义
数据库层面
- ⚠️ 如果已创建表,需要检查列类型
- ⚠️ 必要时创建迁移脚本修正
检查清单
- 所有事件时间字段使用
TIMESTAMPTZ - 默认值使用
now()而非CURRENT_TIMESTAMP - 字段注释使用"自动记录时区"
- 更新文档版本号(v3.4 → v3.6)
- 更新变更记录
- 创建 Changelog 记录修正过程
- 更新 jointo-tech-stack skill 规范
相关文档
总结
本次修正纠正了 v3.5 版本的错误决策,将时间戳规范改回正确的 TIMESTAMPTZ。这符合:
- PostgreSQL 官方最佳实践
- ADR 006 架构决策
- 语义正确性(事件时间是绝对时间点)
- 多时区支持需求
重要提醒:所有记录"真实世界发生时间点"的字段,必须使用 TIMESTAMPTZ。