问题描述
用的Jackson,调试时发现后端返回的2022-02-08,但是前端收到的是2022-02-07,比预期的少了一天;
- 数据库的数据格式为 date
- java实体类的日期格式为 java.util.Date
原因分析
根本原因:时区问题;
后端在实体类中的日期字段上,配置了Jackson的日期格式化:JsonFormat("yyyy-MM-dd")
,如下所示:
@JsonFormat(pattern = "yyyy-MM-dd")
private Date date;
这里的JsonFormat没有配置时区,而Jackson默认的时区为 UTC协调时间时(比GMT格林威治时间准确,GMT已被淘汰),比中国时间少了8个小时;
所以这个时候,后端Jackson在格式化日期时,会先将数据库中查询到的2022-02-08
减去 8小时
(数据库中的日期为Date类型,没有具体的时间),然后才返回前端;
所以前端接收的日期会少一天;
解决办法
配置时区GMT+8
,如下所示:
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date date;
延伸
关于Jackson的源码文档的错误问题:
在JsonFormat的源码文档中,写的是如果不设置时区,默认应该是选择系统所在地区的时区;
/**
* {@link java.util.TimeZone} to use for serialization (if needed).
* Special value of {@link #DEFAULT_TIMEZONE}
* can be used to mean "just use the default", where default is specified
* by the serialization context, which in turn defaults to system
* defaults ({@link java.util.TimeZone#getDefault()}) unless explicitly
* set to another locale.
*/
public String timezone() default DEFAULT_TIMEZONE;
而我们这里的系统时区应该是 Asia/Shanghai
,运行下面的代码:
System.out.println(TimeZone.getDefault());
可以看到控制台打印如下:
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=31,lastRule=null]
所以按理说,如果我们不设置时区,应该采用中国时区,但是为啥用了UTC标准时区呢?
通过查找相关资料,找到了官方的解释,说是文档错误,会修复,修复版本为2.9.0
以下是Jackson 官方解释:
下面是2.9.0版本的更新记录,修复了上面的文档错误的bug:
所以根据问题还是在于时区的设置问题;
总结
出现前后端日期不一致的情况,首先就是要查看时区设置是否正确;
正确的时区设置如下:
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date date;
评论区