时间校验这个问题,我在网上找了很多资料,有用正则表达式的、有用格式工具类的。
其实都能实现时间校验,既然两种方式都能实现,那么使用哪种方式更好呢?
先告诉大家一个结论吧,我更倾向于用日期工具类来实现。接下来给大家分析一下。
先来看一个简单的日期的正则表达式的规则,年份4位数字,月份2位数字,日2位数字,时2位数字,分2位数字,秒2位数字。
String regex = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$";
但是日期校验真的是简单的几位数字的组合吗?咱们来做个测试
注意看第二个日期“2022-13-31 32:12:21”,这明显是个错误的日期,没有13月,也没有32时,但是根据正则表达式来判断的话,是符合规则的。所以说明我们的正则表达式的规则是不完善的。
1、年的规则就是4位数字(这里就这么简单,也可以从19XX年开始)
2、月的2位数字的范围是01-12
3、日的2位数字的范围是01-31
4、时的2位数字的范围是00-23
5、分的2位数字的范围是00-59
5、秒的2位数字的范围是00-59
于是可以得到下面这个正则表达式:
String regex = "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([0-2][0-3]):([0-5][0-9]):([0-5][0-9])$";
进过测试可以看到2022-13-31 32:12:21
这个日期已经被判定为错误日期了。
可是这就完了吗?当然没有,在来看个例子:
日期中还有一个特点就是,每4年会闰年,所以2月的最后一天到几号,就不是那么简单了
所以现在的表达式还需要完善闰年的规则。。。
闰年的规则如下:
(不知道的赶紧学习一下,这都不知道,太丢人了)
一般的年份
:除以4,有余数的是平年,没有余数的是闰年,
整百的年份(世纪年)
:那么该年份除以400,有余数的是平年,没有余数的是闰年。
String regex = "这个正则表达式我写不出来。写不出来的原因:正则表达式说白了只是个模板,好像不能做复杂的逻辑判断。"
既然自己写不出来,那就去网上查一下资料,看一下其他大神是怎么实现的。
我找到一个判断闰年的,但是前提是他把年份的范围规定死了,然后把闰年穷举出来,然后做一个简单的逻辑控制。
也算是一定范围内实现了日期格式的判定。
也是这个原因让我放弃了用正则表达式,本人对正则表达式研究比较浅薄,如果真的可以实现还希望大佬们可以指点一下。
使用SimpleDateFormat工具类,就不需要考虑规则了,这些人家都考虑好了,咱们只需要定义日期格式就行了。
主要原理是:SimpleDateFormat不能格式化、格式化不对的时间字符串都是不符合规则的。
核心代码如下:
public static boolean isValidDate(String dateStr, String dateFormatPattern) {
SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatPattern);
dateFormat.setLenient(false);
try {
Date parsedDate = dateFormat.parse(dateStr);
return dateStr.equals(dateFormat.format(parsedDate));
} catch (ParseException e) {
return false;
}
}
再封装一层
public static boolean isValidDate(String dateStr) {
return isValidDate(dateStr, "yyyy-MM-dd HH:mm:ss");
}
测试一下,可以看到日期字符串
和日期格式
只要有一点不一致,就会被判定为不符合规则。
然后再测试几个错误时间,可以看到2022-13-31 32:12:21
和2023-02-31 00:15:00
都被判定为格式错误了!
终于整理完了!
其实结果很简单,但是我觉得过程也很重要,虽然走了很多弯路,但是值得被记录下来。
本来还有想梳理一下关于LocalDate东西,和java.util.Date对比一下,有什么区别,但是考虑到篇幅。。。就不放在一起了。