# jointo-tech-stack Skill 时区规范更新 > **日期**:2026-01-29 > **类型**:Skill 更新 > **影响范围**:`jointo-tech-stack` skill 中的 `database.md` 和 `backend.md` --- ## 变更概述 更新 `jointo-tech-stack` skill 中的时区规范,将所有事件时间戳从 `TIMESTAMP WITHOUT TIME ZONE` 改为 `TIMESTAMPTZ`,与项目架构决策(ADR 006)保持一致。 --- ## 变更详情 ### 1. database.md 更新 **文件**:`.claude/skills/jointo-tech-stack/references/database.md` #### 修正 1:表结构示例 **修正前**: ```sql 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 ``` **修正后**: ```sql created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ ``` #### 修正 2:字段注释 **修正前**: ```sql COMMENT ON COLUMN folders.created_at IS '创建时间(UTC)'; ``` **修正后**: ```sql COMMENT ON COLUMN folders.created_at IS '创建时间(自动记录时区)'; ``` #### 修正 3:核心要点 **修正前**: ```markdown - 数据库使用 `TIMESTAMP WITHOUT TIME ZONE` ``` **修正后**: ```markdown - 数据库事件时间使用 `TIMESTAMPTZ`(自动记录时区) ``` ### 2. backend.md 更新 **文件**:`.claude/skills/jointo-tech-stack/references/backend.md` #### 修正 1:核心原则 **修正前**: ```markdown 3. **数据库使用 TIMESTAMP WITHOUT TIME ZONE** - PostgreSQL 使用 `TIMESTAMP WITHOUT TIME ZONE` - 应用层保证时区一致性 ``` **修正后**: ```markdown 3. **数据库使用 TIMESTAMPTZ 记录事件时间** - PostgreSQL 使用 `TIMESTAMPTZ` 记录所有真实世界时间点 - 数据库自动处理时区转换 - 符合 PostgreSQL 最佳实践 ``` #### 修正 2:数据库层规范示例 **修正前**: ```sql created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, ``` **修正后**: ```sql created_at TIMESTAMPTZ NOT NULL DEFAULT now(), ``` #### 修正 3:时区规范检查清单 **修正前**: ```markdown - [ ] 数据库表使用 `TIMESTAMP WITHOUT TIME ZONE` ``` **修正后**: ```markdown - [ ] 数据库表使用 `TIMESTAMPTZ` 记录事件时间 ``` --- ## 修正原因 ### 1. 符合架构决策 根据 [ADR 006: 使用 TIMESTAMPTZ 记录事件时间戳](../../architecture/adrs/006-timestamptz-for-event-timestamps.md),项目已正式决定: - ✅ 所有事件时间必须使用 `TIMESTAMPTZ` - ❌ 禁止使用 `TIMESTAMP WITHOUT TIME ZONE` 记录事件时间 - ✅ 默认值使用 `now()` 而非 `CURRENT_TIMESTAMP` ### 2. PostgreSQL 最佳实践 PostgreSQL 官方文档明确推荐使用 `TIMESTAMPTZ` 记录真实世界时间点: > For timestamp with time zone, the internally stored value is always in UTC. An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. ### 3. 语义正确性 `created_at`、`updated_at` 等字段表示**真实世界中事件发生的时间点**,这是一个**绝对时间**,必须包含时区信息。 --- ## 影响范围 ### Skill 文档 - ✅ `database.md` - 数据库设计规范 - ✅ `backend.md` - 后端开发规范 ### 项目文档 需要同步更新的文档(已完成或计划中): - ✅ `docs/architecture/datetime-timezone-standards.md` - ✅ `docs/architecture/adrs/006-timestamptz-for-event-timestamps.md` - ⏳ `docs/requirements/backend/04-services/project/folder-service.md` - ⏳ `docs/requirements/backend/04-services/user/user-service.md` - ⏳ `docs/requirements/backend/04-services/user/credit-service.md` - ⏳ 其他服务文档 --- ## 后续行动 ### 1. 更新所有服务文档 将所有服务文档中的时间戳字段从 `TIMESTAMP WITHOUT TIME ZONE` 改为 `TIMESTAMPTZ`: ```bash # 搜索需要更新的文档 grep -r "TIMESTAMP WITHOUT TIME ZONE" docs/requirements/backend/ ``` ### 2. 创建数据库迁移脚本 为现有表创建迁移脚本,将时间戳列类型从 `TIMESTAMP WITHOUT TIME ZONE` 改为 `TIMESTAMPTZ`: ```sql -- 迁移脚本示例 ALTER TABLE users ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC', ALTER COLUMN updated_at TYPE TIMESTAMPTZ USING updated_at AT TIME ZONE 'UTC', ALTER COLUMN deleted_at TYPE TIMESTAMPTZ USING deleted_at AT TIME ZONE 'UTC'; -- 更新默认值 ALTER TABLE users ALTER COLUMN created_at SET DEFAULT now(), ALTER COLUMN updated_at SET DEFAULT now(); ``` ### 3. 验证和测试 - [ ] 运行集成测试 - [ ] 验证时区转换正确性 - [ ] 性能基准测试 --- ## 相关文档 - [ADR 006: 使用 TIMESTAMPTZ 记录事件时间戳](../../architecture/adrs/006-timestamptz-for-event-timestamps.md) - [时间与时区规范](../../architecture/datetime-timezone-standards.md) - [时间戳规范重大修正 Changelog](2026-01-29-timestamptz-standard-correction.md) - [PostgreSQL Documentation - Date/Time Types](https://www.postgresql.org/docs/current/datatype-datetime.html) --- ## 总结 `jointo-tech-stack` skill 已更新为正确的时区规范,确保所有开发者在编写代码时遵循统一的标准: 1. **事件时间使用 TIMESTAMPTZ**:记录真实世界时间点 2. **默认值使用 now()**:简洁且符合 PostgreSQL 习惯 3. **注释说明时区处理**:明确"自动记录时区" 这个更新确保了 skill 与项目架构决策的一致性,为后续开发提供正确的指导。