开发中遇到有一个日期为1990-08-01(date)的数据存入表的生日字段,保存成功,但是select查询时发现生日变成了1990-07-31。调查后查明是因为java使用的时区与数据库使用的时区不同导致
- 数据库的链接配置为:serverTimezone=Asia/Shanghai,存在夏令时,进入夏令时会时钟快一个小时,离开夏令时时钟慢一个小时。
- 项目中时间格式化配置为:GMT+8,不存在夏令时
因此项目中的日期传入mysql数据库时,mysql会判断时间如果是在夏令时范围内自动减少1小时,导致日期提前了1天。
- 夏令时
CDT:为夏令时时间
CST:为中国、古巴的标准时间或美国、澳大利亚的中部时间。
夏令时:1986年4月,中国中央有关部门发出“在全国范围内实行夏时制的通知”,具体做法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。
从1986年到1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。在夏令时开始和结束前几天,新闻媒体均刊登有关部门的通告。1992年起,夏令时暂停实行
Asia/Shanghai:中国本地时间),会处理中国夏令时
GMT+8:东八区时间,不会处理中国夏令时
- 解决
方案1
问题是项目与数据库的时区不同导致的,要解决就是要把2者的时区设置成相同时区,将所有时间设置为GMT+8标准时间。
- 修改mysql连接
# 将mysql的时区Asia/Shanghai改为GMT+8,GMT%2B8为GMT+8的转义编码
&serverTimezone=GMT%2B8
2.启动类的main方法中设置时区
@SpringBootApplication
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
SpringApplication.run(AdminApplication.class, args);
}
返回前端的时候,在实体类上设置 json格式
@JsonFormat(timezone = “Asia/Shanghai”, pattern = “yyyy/MM/dd”)
方案2
如果觉得改项目的时区配置有风险,或者给配置类麻烦,也可以只改实体类用LocalDateTime类型存属性,每次字段插入数据库时增加1小时就不会导致日期提前1天了,这样的改动最小。适合存储生日这样不会变化的字段。