16 KiB
16 KiB
时区国际化需求
元数据
- 需求编号:2026-01-21-002-04
- 创建时间:2026-01-21
- 创建人:SSOT 架构师
- 状态:已完成
- 优先级:高
- 父需求:2026-01-21-002-项目国际化需求
需求概述
实现时区国际化功能,支持用户设置时区偏好,根据用户时区显示时间,支持常用时区。所有时间字段存储为 UTC 时间,在 Service 层进行时区转换,使用 Redis 缓存时区配置,时区切换后立即刷新页面重新加载时间数据。
目标
- 时区设置:支持用户设置时区偏好(用户级别,优先级:用户 > 租户 > 系统)
- 时区转换:所有时间字段根据用户时区自动转换(在 Service 层进行)
- 时区支持:支持常用时区(时区列表固定存储在数据库中)
- 时区保存:时区偏好保存在用户配置中
- 系统默认:支持系统默认时区配置
- 缓存管理:使用 Redis 缓存时区配置,提高性能
- 页面刷新:时区切换后立即刷新页面,重新加载时间数据
业务上下文
当前问题
- 系统时间显示固定,无法根据用户所在时区调整
- 缺乏时区设置功能,用户体验不佳
- 跨时区用户看到的时间不准确
- 缺乏时区缓存机制,性能不佳
业务场景
时区国际化
├─ 用户登录
│ ├─ 读取用户时区偏好(优先级:用户 > 租户 > 系统)
│ ├─ 从 Redis 缓存读取时区配置
│ └─ 在 Service 层根据用户时区转换时间
├─ 数据展示
│ ├─ 所有时间字段根据用户时区转换
│ ├─ 创建时间:根据用户时区转换
│ ├─ 更新时间:根据用户时区转换
│ └─ 操作时间:根据用户时区转换
├─ 日志记录
│ ├─ 操作日志:记录用户时区
│ └─ 系统日志:记录系统时区
├─ 时区切换
│ ├─ 用户选择新时区
│ ├─ 更新用户时区偏好
│ ├─ 清除 Redis 缓存
│ └─ 刷新页面,重新加载时间数据
└─ 时区管理
├─ 时区列表固定存储在数据库
├─ 后续不允许用户调整时区列表
└─ 支持时区查询和显示
应用场景
- 跨国用户:不同国家和地区的用户使用系统,需要看到符合自己时区的时间
- 移动办公:用户在不同时区办公,需要看到当地时区的时间
- 系统部署:系统部署到不同时区,需要支持当地时区
- 多租户场景:不同租户可能需要不同的默认时区
功能需求
核心功能
功能 1:时区设置
- 描述:提供时区设置功能,支持用户设置时区偏好
- 验收标准:
- 支持用户设置时区偏好
- 支持常用时区(如:UTC、Asia/Shanghai、America/New_York 等)
- 支持系统默认时区配置
- 时区设置立即生效
- 时区设置记录审计日志
- 优先级:高
- 依赖关系:依赖用户表(sys_user)、时区表(sys_timezone)
功能 2:时区转换
- 描述:实现时区转换功能,所有时间字段根据用户时区自动转换
- 验收标准:
- 所有时间字段根据用户时区自动转换
- 时区转换在 Service 层进行
- 支持创建时间、更新时间、操作时间的转换
- 支持日志时间的转换
- 时区转换准确无误
- 时区转换时间 < 10ms
- 优先级:高
- 依赖关系:依赖时区设置功能、TimeZoneUtils 工具类
功能 3:时区显示
- 描述:实现时区显示功能,显示当前用户时区
- 验收标准:
- 显示当前用户时区
- 显示时区偏移(如:UTC+8)
- 支持时区切换提示
- 时区信息从数据库读取
- 优先级:中
- 依赖关系:依赖时区设置功能
功能 4:时区列表管理
- 描述:提供时区列表查询功能,时区列表固定存储在数据库中
- 验收标准:
- 时区列表从数据库读取
- 时区列表固定,后续不允许用户调整
- 支持时区列表查询
- 支持时区列表缓存(Redis)
- 支持默认时区标识
- 优先级:高
- 依赖关系:依赖时区表(sys_timezone)
功能 5:时区切换
- 描述:提供时区切换功能,支持用户切换时区
- 验收标准:
- 支持用户切换时区
- 时区切换后清除 Redis 缓存
- 时区切换后立即刷新页面
- 时区切换响应时间 < 500ms
- 时区切换记录审计日志
- 优先级:高
- 依赖关系:依赖时区设置功能、Redis 缓存
功能 6:时区缓存管理
- 描述:实现时区配置的缓存管理,使用 Redis 缓存时区配置
- 验收标准:
- 时区列表使用 Redis 缓存
- 用户时区使用 Redis 缓存
- 时区切换时清除相关缓存
- 缓存失效时间合理(时区列表 24 小时,用户时区 30 分钟)
- 优先级:高
- 依赖关系:依赖 Redis 缓存
功能 7:时区优先级管理
- 描述:实现时区优先级管理,支持用户 > 租户 > 系统的优先级
- 验收标准:
- 用户时区优先级最高
- 租户时区优先级次之
- 系统时区优先级最低
- 优先级判断准确无误
- 优先级:中
- 依赖关系:依赖用户表、租户表、系统配置
非功能需求
性能需求
- 转换时间:时区转换时间 < 10ms
- 响应时间:时区切换响应时间 < 500ms
- 缓存命中率:时区缓存命中率 ≥ 95%
- 并发支持:支持 1000+ 并发用户
安全需求
- 认证方式:使用现有的 Spring Security 认证机制
- 授权机制:所有用户都可以设置时区
- 审计日志:记录时区设置变更日志
- 数据验证:验证时区ID的有效性
兼容性需求
- 时区库:使用 Java TimeZone API(Java 21 内置)
- 数据库兼容性:兼容现有的数据库时间字段(LocalDateTime)
- Redis 兼容性:兼容现有的 Redis 缓存配置
- 前端兼容性:支持主流浏览器(Chrome、Firefox、Edge、Safari)
可维护性需求
- 代码可读性:代码符合项目编码规范,注释完整
- 测试覆盖率:单元测试覆盖率 ≥ 80%
- 日志记录:完整的日志记录,便于问题排查
- 文档完善:完整的接口文档和使用文档
可扩展性需求
- 时区扩展:支持未来添加新的时区
- 租户扩展:支持未来添加租户级别的时区配置
- 缓存扩展:支持未来添加更多缓存策略
数据需求
数据依赖
- 依赖用户表(sys_user)
- 依赖时区表(sys_timezone)
- 依赖 Redis 缓存
- 依赖现有的 Spring Boot 框架
- 依赖现有的认证授权机制
数据存储需求
时区表(sys_timezone)
CREATE TABLE `sys_timezone` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '时区ID',
`timezone_id` varchar(50) NOT NULL COMMENT '时区ID(如:Asia/Shanghai)',
`timezone_name` varchar(100) NOT NULL COMMENT '时区名称(如:中国标准时间)',
`timezone_offset` varchar(10) NOT NULL COMMENT '时区偏移(如:UTC+8)',
`is_default` tinyint(1) DEFAULT '0' COMMENT '是否默认时区(0否 1是)',
`sort_order` int DEFAULT '0' COMMENT '排序',
`status` char(1) DEFAULT '0' COMMENT '状态(0正常 1停用)',
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT '' COMMENT '更新者',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_timezone_id` (`timezone_id`),
KEY `idx_status` (`status`),
KEY `idx_sort_order` (`sort_order`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='时区配置表';
用户表修改(sys_user)
ALTER TABLE `sys_user` ADD COLUMN `time_zone` varchar(50) DEFAULT 'Asia/Shanghai' COMMENT '时区ID' AFTER `lang_code`;
数据流转需求
用户登录
├─ 读取用户时区偏好(优先级:用户 > 租户 > 系统)
├─ 从 Redis 缓存读取时区配置
├─ 在 Service 层根据用户时区转换时间
└─ 显示转换后的时间
时区切换
├─ 用户选择新时区
├─ 验证时区ID有效性
├─ 更新用户时区偏好
├─ 清除 Redis 缓存
├─ 刷新页面
└─ 重新加载时间数据
数据查询
├─ 从数据库读取 UTC 时间
├─ 在 Service 层根据用户时区转换
└─ 返回转换后的时间
数据保存
├─ 接收用户时区时间
├─ 在 Service 层转换为 UTC 时间
└─ 保存 UTC 时间到数据库
缓存策略需求
- 时区列表缓存:缓存键
sys:timezone:list,缓存时间 24 小时 - 用户时区缓存:缓存键
user:timezone:{userId},缓存时间 30 分钟 - 数据缓存:在原有缓存键基础上添加时区后缀,如
dict:data:zh_CN:Asia/Shanghai - 缓存清除:时区切换时清除用户时区缓存,时区列表更新时清除时区列表缓存
接口需求
时区管理接口
1. 获取时区列表
- 接口路径:GET /system/timezone/list
- 接口描述:获取时区列表
- 请求参数:无
- 响应数据:
{ "code": 200, "msg": "操作成功", "data": [ { "id": 1, "timezoneId": "Asia/Shanghai", "timezoneName": "中国标准时间", "timezoneOffset": "UTC+8", "isDefault": true, "sortOrder": 1, "status": "0" } ] }
2. 获取当前用户时区
- 接口路径:GET /system/timezone/current
- 接口描述:获取当前用户时区
- 请求参数:无
- 响应数据:
{ "code": 200, "msg": "操作成功", "data": "Asia/Shanghai" }
3. 切换时区
- 接口路径:POST /system/timezone/switch
- 接口描述:切换用户时区
- 请求参数:
{ "timeZone": "America/New_York" } - 响应数据:
{ "code": 200, "msg": "时区切换成功", "data": null }
4. 获取默认时区
- 接口路径:GET /system/timezone/default
- 接口描述:获取系统默认时区
- 请求参数:无
- 响应数据:
{ "code": 200, "msg": "操作成功", "data": "Asia/Shanghai" }
业务规则
- 时区偏好唯一性:每个用户只能有一个时区偏好
- 系统默认时区:系统必须有默认时区配置
- 时区转换准确性:时区转换必须准确无误
- 时区切换权限:所有用户都可以切换时区
- 时区缓存:时区配置需要缓存,提高性能
- 时区优先级:用户时区 > 租户时区 > 系统时区
- 时区列表固定:时区列表固定存储在数据库中,后续不允许用户调整
- 时间存储:所有时间字段存储为 UTC 时间
- 转换层级:时区转换在 Service 层进行
- 页面刷新:时区切换后立即刷新页面,重新加载时间数据
技术约束
- Spring Boot 版本:3.5.7
- Java 版本:21
- 时区库:Java TimeZone API(Java 21 内置)
- 缓存方案:Redis
- 必须使用现有的认证授权机制:不能引入新的认证方式
- 必须使用现有的 Redis 缓存:不能引入新的缓存方案
- 必须使用现有的数据库连接池:不能引入新的数据库连接方案
成功标准
- 支持常用时区(至少 8 个常用时区)
- 支持用户设置时区偏好
- 所有时间字段根据用户时区自动转换
- 时区转换准确无误
- 时区转换时间 < 10ms
- 时区切换响应时间 < 500ms
- 时区缓存命中率 ≥ 95%
- 单元测试覆盖率 ≥ 80%
- 支持 1000+ 并发用户
风险评估
| 风险 | 影响程度 | 发生概率 | 缓解措施 |
|---|---|---|---|
| 时区转换错误 | 高 | 低 | 使用成熟的 Java TimeZone API,充分测试 |
| 时区缓存不一致 | 中 | 低 | 实现时区缓存同步机制,时区切换时清除缓存 |
| 时区切换导致时间显示错误 | 中 | 低 | 实现时区切换验证机制,刷新页面重新加载数据 |
| 性能问题 | 中 | 中 | 使用 Redis 缓存,优化转换逻辑,支持并发 |
| 夏令时问题 | 中 | 低 | 使用 Java TimeZone API 自动处理夏令时 |
| 历史数据处理 | 低 | 低 | 历史数据不做处理,只处理新数据 |
测试需求
单元测试
- TimeZoneUtils 工具类测试
- 时区转换功能测试
- 时区验证功能测试
- 缓存功能测试
集成测试
- 时区设置功能测试
- 时区切换功能测试
- 时区查询功能测试
- 缓存同步测试
性能测试
- 时区转换性能测试(< 10ms)
- 时区切换响应时间测试(< 500ms)
- 并发用户测试(1000+)
- 缓存命中率测试(≥ 95%)
兼容性测试
- 不同时区转换测试
- 夏令时转换测试
- 跨时区数据查询测试
- 浏览器兼容性测试
异常测试
- 无效时区ID测试
- 缓存失败测试
- 数据库连接失败测试
- 并发冲突测试
实施计划
阶段 1:数据库设计(1 天)
- 创建时区表(sys_timezone)
- 修改用户表(sys_user)
- 插入常用时区数据
阶段 2:实体类和工具类开发(2 天)
- 创建 SysTimezone 实体类
- 修改 SysUser 实体类
- 创建 TimeZoneUtils 工具类
- 创建 SysTimezoneMapper
阶段 3:Service 层开发(3 天)
- 创建 ISysTimezoneService
- 创建 ISysUserTimeZoneService
- 实现时区查询功能
- 实现时区设置功能
- 实现时区转换功能
- 实现缓存管理功能
阶段 4:Controller 层开发(2 天)
- 创建 SysTimezoneController
- 实现时区列表查询接口
- 实现当前时区查询接口
- 实现时区切换接口
- 实现默认时区查询接口
阶段 5:AOP 切面开发(2 天)
- 创建时区转换切面
- 实现自动时区转换逻辑
- 实现缓存管理逻辑
阶段 6:前端集成(3 天)
- 创建时区切换组件
- 创建时区显示组件
- 实现时区选择器
- 实现页面刷新逻辑
阶段 7:测试(3 天)
- 单元测试
- 集成测试
- 性能测试
- 兼容性测试
- 异常测试
阶段 8:文档和部署(2 天)
- 编写接口文档
- 编写使用文档
- 部署到测试环境
- 部署到生产环境
总计:18 天
依赖关系
- 依赖用户表(sys_user)
- 依赖时区表(sys_timezone)
- 依赖 Redis 缓存
- 依赖现有的 Spring Boot 框架
- 依赖现有的认证授权机制
- 依赖现有的 MyBatis Plus 框架