前言
本篇文章讨论关于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 //报错

被折叠的 条评论
为什么被折叠?



