侧边栏壁纸
  • 累计撰写 79 篇文章
  • 累计创建 84 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

后端返回的日期少了一天

汤圆学Java
2022-05-09 / 0 评论 / 0 点赞 / 61 阅读 / 1,442 字
温馨提示:
本文最后更新于 2022-05-09,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

问题描述

用的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 官方解释

image-20220426182721462

下面是2.9.0版本的更新记录,修复了上面的文档错误的bug:

image-20220426182816354

所以根据问题还是在于时区的设置问题;

总结

出现前后端日期不一致的情况,首先就是要查看时区设置是否正确;

正确的时区设置如下:

@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date date;
0

评论区