Jackson/Spring 1900年日期格式化异常(相差5分钟)

本文探讨了在开发中Jackson解析日期格式时遇到的1900-01-08日期显示错误问题,通过配置全局日期处理器和去除@JsonFormat,成功解决了时区异常和日期丢失一天的问题。

问题

在开发过程中,遇到1900-01-08,格式为yyyy-MM-dd,接口返回的却总是少一天,变成了1900-01-07,导致页面显示不正确。

排查

因为使用了jackson的@JsonFormat注解,第一反应是时区不对,但经测试,调整时区并无效果,切2022-10-10等普通日期是可以正常显示的。然后将格式化精确到秒,发现只差5分钟,这就令人非常费解了,网上查到的资料也比较凌乱。

接口返回的数据是没问题的,便将思路放在了json格式上,最后经过单元测试,确认是Jackson的问题。结合资料和Debug,Jackson默认的日期格式化类是SimpleDateFormat,在测试了Jackson、jdk、hutool等日期工具后,确认SimpleDateFormat存在异常。

测试代码如下:

public static void test() throws JsonProcessingException, ParseException {
    String str = "1900-01-08 00:00:00";
    Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(str);
    System.out.println("date:" + date + "\n");
    // date:Mon Jan 08 00:00:00 CST 1900

    StdDateFormat format = new StdDateFormat();
    System.out.println("std:" + format.format(date));
    // std:1900-01-07T15:54:17.000+00:00
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    System.out.println("simple:" + dateFormat.format(date));
    // simple:1900-01-08 00:00:00
    System.out.println("DateUtil:" + DateUtil.formatDateTime(date));
    // DateUtil:1900-01-08 00:00:00
    System.out.println();

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setDateFormat(dateFormat);
    System.out.println(objectMapper.writer().writeValueAsString(date));
    // "1900-01-08 00:00:00"
}

解决方案

方案一

数据库的日期直接存12点。通过拦截器或硬编码,在保存/编辑的时候处理数据。

tip:实现难度低,侵入性强,不推荐

方案二

自定义@jsonformat的日期解析器,解决这个bug。

tip:实现难度高,不推荐

方案三(推荐)

全局Jackson配置,指定日期处理器,并去掉字段上面的@JsonFormat

tip:实现难度低,侵入度低,但是无法再使用注解自定义格式,如果全局统一格式的话,建议采用此方法。

配置代码如下:

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {


    /**
     * 统一日期格式化
     *
     * @return void
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        // 指定日期格式化工具
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(0, jackson2HttpMessageConverter);
    }

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值