奇怪的知识--日期解析

前言

本篇文章讨论关于java中日期的解析行为,具体产生该文章问题源头来自对日期格式的校验。

问题来源

需求:外部调用接口传递参数中含有Date类型的参数,入参只能是Date类型 yyyy-MM-dd
结果:传入诸如 2022-12-1522 这种也是能成功的。

问题来源

从常规的解析和接受来说,在入参字段上面加入@JsonFormat(pattern = “yyyy-MM-dd”)或@DateTimeFormat(pattern = “yyyy-MM-dd”),类似下方代码

 	@DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date updateDateFrom;

从简单的认知不难理解只有符合pattern的格式才能传入,否则会报错。事实上确实传递一些混乱的字符串是会抛出异常的。但是类似 2022-12-1522 这种的却不行。当然由于大部分的这种传参是前端控的,理论上不会存在这种可能性。这里发现这个问题的时候是需要提供对外接口供另外的系统调用,而另外的系统我们无法控制,就需要在本系统做好校验。

问题解析

要先解决问题之前就得知道,是哪里导致这个解析成功,解析成功后的结果有是什么。
最开始我认为可能是注解解析的时候的问题,后面查看解析的源码中发现,底层依然是调用的SimpleDateFormat来解析的。这里不过多解析源码。即使用SimpleDateFormat解析也能成功。


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTest01 {
    public static void main(String[] args) throws ParseException {
        String text = "2022-12-1522";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = simpleDateFormat.parse(text);
        String format = simpleDateFormat.format(parse);
        System.out.println(text);  //结果 2022-12-1522
        System.out.println(format); //结果 2027-01-30
    }
}

这里不过多赘述解析的过程,感兴趣的自行查看parse方法。这里仅对结果做分析,2022-12-1522是如何得到2027-01-30的,我们试着改变一下输入的值。

public class DateTest01 {
    public static void main(String[] args) throws ParseException {
        String text = "2022-12-33";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = simpleDateFormat.parse(text);
        String format = simpleDateFormat.format(parse);
        System.out.println(text);//结果 2022-12-33
        System.out.println(format);//结果 2023-01-02
    }
}

可以发现这里超出的日期会向上以为进位。日->月->年。
衍生:月份也可以超过12。且是可以值为负数的,会向后退位。
类似下面的输入都是可以解析的

String text = "0-12322-3322";
String text = "25-1-3322";
//对应2021-11-30,就是2022-00表示2022-01的上一个月2021-12,
//2022-00-00 表示2021-12-01的上一天 2021-11-30
String text = "2022-00-00"; //对应2021-11-30
String text = "2022--50--10"; //2017-09-20 这里的-代表负数

解决问题

回到问题本身,是为了对日期格式做校验。其实这里主要是为了对外接口传值做校验。原来的日期校验行不通了,因为只要使用了Date类型接收了就无法校验上面的情况。所以需要改用String接收传递的日期的值,代码中转换为Date类型,再将该Date类型转化为String类型,对比传入的String的值是否相等。

public class DateTest01 {
    public static void main(String[] args) throws ParseException {
        String text = "2022-12-1522";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = simpleDateFormat.parse(text);
        String format = simpleDateFormat.format(parse);
        System.out.println(text);
        System.out.println(format);
        System.out.println(text.equals(format));//使用这个判断格式是否符合预期
    }
}

题外

使用hutool工具解析日期

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * @Description: 类描述
 * @DATE: 2022/11/21 16:53
 * @Author: PBC
 */
public class DateTest01 {
    public static void main(String[] args) throws ParseException {
        String text = "2022-12-1522";
        DateTime parse1 = DateUtil.parse(text, "yyyy-MM-dd");
        System.out.println(parse1);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = simpleDateFormat.parse(text);
        String format = simpleDateFormat.format(parse);
        System.out.println(text);
        System.out.println(format);
        System.out.println(text.equals(format));
    }
}

使用hutool工具DateUtil.parse(text, “yyyy-MM-dd”);发现报错了。
在这里插入图片描述
就在我满怀希望发现可以通过hutool工具直接解决的时候,拿到项目中使用发现又不报错了。
在这里插入图片描述
对比本地测试和项目中的hutool工具,发现是版本的问题,高版本的是会报错的,低版本的不会。具体修改的版本没有研究。提供两个环境的版本号。
项目中使用:5.1.0 //不报错
本地测试:5.7.0 //报错

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值