避免时区问题的最佳实践, 数据库, mybatis
避免时区问题的最佳实践
1. 数据库连接配置
# application.properties
# MySQL - 设置服务器时区
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8# PostgreSQL - 设置时区
spring.datasource.url=jdbc:postgresql://localhost:5432/test?options=-c%20TimeZone=Asia/Shanghai
2. 统一时区处理工具类
@Component
public class DateTimeHelper {public static final ZoneId CHINA_ZONE = ZoneId.of("Asia/Shanghai");// 获取当前中国时区时间public static LocalDateTime now() {return LocalDateTime.now(CHINA_ZONE);}// 转换到中国时区public static LocalDateTime toChinaTime(Instant instant) {return LocalDateTime.ofInstant(instant, CHINA_ZONE);}// 转换为Instantpublic static Instant toInstant(LocalDateTime localDateTime) {return localDateTime.atZone(CHINA_ZONE).toInstant();}
}
需要避免的做法
❌ 不推荐
// 避免使用 java.util.Date
private Date createTime;// 避免依赖系统默认时区
private LocalDateTime createTime = LocalDateTime.now();// 避免混合使用不同的时间类型
✅ 推荐
// 使用 java.time 包
private LocalDateTime createTime;
private LocalDate birthday;
private Instant updateTime;// 明确指定时区
private LocalDateTime createTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
总结
场景 | 推荐数据库类型 | 推荐Java类型 | 说明 |
---|---|---|---|
创建/更新时间 | TIMESTAMP | LocalDateTime | 无时区问题 |
日期 | DATE | LocalDate | 纯日期 |
国际化时间 | TIMESTAMP | Instant | 存储时间戳 |
需要时区 | TIMESTAMPTZ | ZonedDateTime | PostgreSQL专用 |
核心建议:
统一使用
java.time
包数据库字段使用 TIMESTAMP/DATETIME
应用层统一时区处理
数据库连接明确指定时区
避免使用
java.util.Date