java正则表达式校验日期格式实例代码
作者:RanLZ
1 引言
我们时常会遇到,判断一个String是不是合法的日期格式。当其是一个正确的日期时,我们还需要判断其格式是否符合我们的规范,常见格式如下:
- yyyyMMdd (20220929)
- yyyy-MM-dd (2022-09-29)
- yyyy/MM/dd (2022/09/29)
- yyyy.MM.dd (2022.09.29)
对于这些不同的格式来说,其实我们只要确定了年月日,再根据不同的格式来微调我们的正则表达式即可。因此本篇讲解以格式 yyyyMMdd
为例。其他格式不再详解,其正则表达式微调即可得到,这里就不赘述了。
2 基础知识
2.1 什么是正确的日期
MSDN中定义的DateTime对象的有效范围是:0001-01-01 00:00:00到9999-12-31 23:59:59。
- 因此我们筛选的日期为
00010101
到99991231
(以格式yyyyMMdd
为例,后文将不再强调)
其次,对于日历中大家都知道的 大月 和 小月,这里也不再赘述。
在小月中有个特殊的 2月
,它一个月只有28 或 29天,而其具体的天数根据是否为 闰年 来决定。
2.2 什么是闰年
我们通过计算方式的不同,将闰年分为 普通闰年 和 世纪闰年。
- 普通闰年:公历年份是4的倍数,且不是100的倍数的,为闰年(如2004年、2020年等就是闰年)。
- 世纪闰年:公历年份是整百数的,必须是400的倍数才是闰年(如1900年不是闰年,2000年是闰年)。
2.3 正则表达式基础
由于正则表达式的知识比较繁多,这里不做过多的介绍。只对本文将用到的表达式进行讲解。
字符 | 描述 |
---|---|
| | 指明两项之间的一个选择,意为或 。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
{n} | n 是一个非负整数。匹配确定的 n 次。 |
[1-9] | [1-9] 表示一个区间,匹配1-9的数字 |
[ABC] | 匹配 […] 中的所有字符,例如 [358] 匹配数字 3、5、8 |
接下来我们将这些简单的字符进行一个组合,看看你是否还能理解他们的意思呢?
正则表达式 | 描述 | 举例文本 | 错误文本 |
---|---|---|---|
\d{3} | 3个数字都是0-9的间的数字 | 237、832、129 | a37、ufo |
\d{3}[1-9] | 前3个数字都是0-9的间的数字,第四个数字是1-9直接的数字 | 2372、4041、9001 | 8720、2020 |
[7-9]|[523] | 该数字要么是7-9之间的一个数,要么是2,3,5其中的一个数字 | 7、5、2 | 1、4、6 |
简单的学会使用正则表达式了,那我们就开始正式的开始书写吧。
3 构造正则表达式
3.1 闰年的情况
为了方便后面的表示,我们将 yyyy 变为 y1y2y3y4
3.1.1 世纪闰年的情况
- 世纪闰年:公历年份是整百数的,必须是400的倍数才是闰年(如1900年不是闰年,2000年是闰年)。
由 世纪闰年 的定义我们可以知道,y3 和 y4 一定是0的,因此可得如下表格:
y1 | y2 | y3 | y4 |
---|---|---|---|
待定 | 待定 | 0 | 0 |
现在来讨论 y1 和 y2,由定义可知,我们可知 y1y2这个二位数一定是4的倍数。4的倍数的二位数一共有:
- 04、08、12、16、20、
- 24、28、32、36、40、
- 44、48、52、56、60、
- 64、68、72、76、80、
- 84、88、92、96、
相信大家也看出规律了,因此可得如下表格:
y1 | y2 | y1y2 | y3 | y4 |
---|---|---|---|---|
0 | [48] | 0[48] | 0 | 0 |
[2468] | [48] | [2468][048] | 0 | 0 |
[3579] | [48] | [3579][26] | 0 | 0 |
可以看到,此时有3种情况,这里我们用 | 将其联系起来成为一条正则表达式,如下:
((0[48]|[2468][048]|[3579][26])00)
3.1.2 普通闰年的情况
- 普通闰年:公历年份是4的倍数,且不是100的倍数的,为闰年(如2004年、2020年等就是闰年)。
因此在此我们只需要判断,y1y2y3y4 是否为4的倍数即可,但这里也想上面把所有情况列出来找规律吗?这里可是4位数,情况将远远大于2位数的情况。这里我们来找找有没有什么可以减少位数的方法呢?
所以 y1y200 不管 y1y2 为何值都为4的倍数,可得下表:
y1 | y2 | y1y2 | y3 | y4 |
---|---|---|---|---|
\d | \d | \d{2} | 待定 | 待定 |
而我们可以知道,一个为4的倍数的数,只有加上一个为4的倍数,和才能为4的倍数。故我们现在只需要求 y3y4 为4的情况即可,我们按照之前列举的方法可得如下表:
y1 | y2 | y1y2 | y3 | y4 |
---|---|---|---|---|
\d | \d | \d{2} | 0 | [48] |
\d | \d | \d{2} | [2468] | [48] |
\d | \d | \d{2} | [13579] | [26] |
这里我们用 | 将其联系起来成为一条正则表达式,如下:
(\d{2})(0[48]|[2468][048]|[13579][26])
3.1.3 闰年的特殊日期
我们可以知道闰年的特殊之处在于2月29日
这一天是否存在,其他日子不存在闰年与平年的区别。因此我们只需要在闰年的情况下,判断2月29日这一天的日子即可,故可得以下正则表达式:
世纪闰年:(\d{2})(0[48]|[2468][048]|[13579][26])0229 普通闰年:((0[48]|[2468][048]|[3579][26])00)0229
用 | 将其联系起来成为一条正则表达式,如下:
(((\d{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229)
3.2 其他情况
现在解决了 2月29日
这个棘手的问题,对于其他日子,我们将不在区分闰年。看到这你是不是以为就可以直接 \d{4}
来表示y1y2y3y4 了?
看来你忽略了一个条件,在 2.2.1
中我们明确了时间的范围为为 00010101
到 99991231
,但当 y1y2y3y4 为 \d{4}
存在 0000
这个情况,显然这个数据并不在我们合法的范围中。
因此我们可以得到如下的表:
y1 | y2 | y3 | y4 |
---|---|---|---|
\d | \d | \d | [1-9] |
\d | \d | [1-9] | \d |
\d | [1-9] | \d | \d |
[1-9] | \d | \d | \d |
用 | 将其联系起来成为一条正则表达式,如下:
(\d{3}[1-9]|\d{2}[1-9]\d|\d[1-9]\d{2}|[1-9]\d{3})
然后就是构造 月
和 日
的正则表达式了
3.2.1 大月
首先是大月为:01,03,05,07,08,10,12。
正则表达式如下:
(0[13578]|1[02])
大月每月的日子从1日-31日均有。
正则表达式如下:
(0[1-9]|[12]\d|3[01])
故大月的正则表达式为:
((0[13578]|1[02])(0[1-9]|[12]\d|3[01]))
3.2.2 小月
首先是小月为:02,04,06,09,11。(但2月的日子和其他小月不同,这里将排除掉2月)
正则表达式如下:
(0[469]|11)
小月(不含2月)每月的日子从1日-30日均有。
正则表达式如下:
(0[1-9]|[12]\d|30)
故小月(除2月)的正则表达式为:
(0[469]|11)(0[1-9]|[12]\d|30))
3.2.3 2月
因为前面我们已经特殊表示了2月29日,所以这里我们只需要考虑2月的1日到28日,正则表达式如下:
(02(0[1-9]|[1]\d|2[0-8])
3.3 完整表达式
现在我们将全年的年月日均表达出来了,我们将其用 | 联系起来可得如下正则表达式(不包含2月29日):
((\d{3}[1-9]|\d{2}[1-9]\d|\d[1-9]\d{2}|[1-9]\d{3})(((0[13578]|1[02])(0[1-9]|[12]\d|3[01]))|((0[469]|11)(0[1-9]|[12]\d|30))|(02(0[1-9]|[1]\d|2[0-8]))))
4 总结
经过前面的努力,我们得到了如下的两个表达式:
闰年2月29日情况: (((\d{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229) 不含2月29日情况: ((\d{3}[1-9]|\d{2}[1-9]\d|\d[1-9]\d{2}|[1-9]\d{3})(((0[13578]|1[02])(0[1-9]|[12]\d|3[01]))|((0[469]|11)(0[1-9]|[12]\d|30))|(02(0[1-9]|[1]\d|2[0-8]))))
最终我们将这两个情况,用 | 联系起来,我们就得到了校验日期的正则表达式了!
((\d{3}[1-9]|\d{2}[1-9]\d|\d[1-9]\d{2}|[1-9]\d{3})(((0[13578]|1[02])(0[1-9]|[12]\d|3[01]))|((0[469]|11)(0[1-9]|[12]\d|30))|(02(0[1-9]|[1]\d|2[0-8]))))|(((\d{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229)
到此这篇关于java正则表达式校验日期格式的文章就介绍到这了,更多相关java正则校验日期格式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!