1.简介正则表达式可以用来匹配各种模式。本文将在java中使用正则表达式来检测给定字符串是否包含有效日期。2.日期格式概述定义了一个有效的日期,日期格式一般定义为yyyy-MM-dd。考虑到范围年、闰年等的大小,我们先说闰年。普通闰年:公历年是4的倍数,不是100的倍数,就是闰年(比如2004、2020等都是闰年)。世纪闰年:公历中的年份以百为单位,必须是400的倍数才是闰年(比如1900年不是闰年,2000年是闰年)。有效日期示例:2017-12-312020-02-292400-02-29无效日期示例2017/12/31:分隔符不正确2018-1-1:无前导02018-04-31:天数为错误2100-02-29:平年2月只有28天。3.我们需要使用正则表达式来匹配日期。首先定义一个接口DateMatcher,它只提供一个匹配方法。完整解决方案3.1匹配数字创建一个简单的正则模式来格式化字符串:2}$");@Overridepublicbooleanmatches(Stringdate){returnDATE_PATTERN.matcher(date).matches();}}这里我们指定一个有效日期必须由三组破折号分隔的整数,第一组由4个整数组成,其余两组各有两个整数。示例:匹配日期:2017-12-31、2018-01-31、0000-00-00、1029-00-72不匹配日期:2018-01、2018-01-XX、2020/02/093.2匹配的范围dates现在我们已经成功匹配了通用的日期格式,现在我们做进一步的约束,我们把年限制在1900-2999,对月和日同样的约束^((19|2[0-9])[0-9]{2})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$这里我们有三组ofintegers范围被约束((19|2[0-9])[0-9]{2}),它通过匹配一个以19或2X开头的数字后跟几个任意数字(0[1-9]|1[012]),匹配01-12范围内的月份(0[1-9]|12|3[01]),匹配01-31范围内的天数匹配日期:1900-01-01、2205-02-31、2999-12-31不匹配日期:1989-12-31、2018-05-35、2018-13-05、3000-01-01、2018-01-XX3.3matchFebruary29为了匹配2月29,首先要判断闰年,必须匹配1900-2099之间的闰年。如果一个数的最后2位能被4整除,则原数也能被4整除;如果最后两位数字是00,则该数可被100^((2000|2400|2800|(19|2[0-9])(0[48]|[2468][048]|[13579][26]))-02-29)$这个regex由以下部分组成2000|2400|2800匹配一组闰年,在1900-2999范围内,匹配能被400整除的19|20-9,匹配能被4整除但不能被100整除的02-29匹配2月29日,例如匹配日期:2020-02-29、2024-02-29、2400-02-29不匹配日期:2019-02-29、2100-02-29,3200-02-29,2020/02/293.4匹配2月28日2月29日是闰年,我们还要匹配2月28日^(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))$示例:匹配日期:2018-02-01、2019-02-13、2020-02-25不匹配的日期:2000-02-30、2400-02-62、2018/02/283.5。匹配31天的月份3。5将31天的月份1、3、5、7、8、10和12月与31天匹配^(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))$例子:匹配日期:2018-01-31,2021-07-31,2022-08-31未匹配日期:2018-01-32、2019-03-64、2018/01/313.6匹配30天月份4、6、9、11,每个月有30天^(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))$示例:匹配月份:2018-04-30,2019-06-30,2020-09-30不匹配的月份:2018-04-31,2019-06-31,2018/04/303.7聚合日期匹配器现在我们将把上面的所有模式组合成一个满足所有日期约束的匹配器classGregorianDateMatcherimplementsDateMatcher{privatestatic模式DATE_PATTERN=Pattern.compile("^((2000|2400|2800|(19|2[0-9])(0[48]|[2468][048]|[13579][26]))-02-29)$"+"|^(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))$"+"|^(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))$"+"|^(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))$");@Overridepublicbooleanmatches(Stringdate){returnDATE_PATTERN.matcher(date).matches();}}我们使用了“|”匹配28天、29天、30天和31天。至此,我们已经满足了开头介绍的日期的所有约束条件。3.8性能描述解析复杂的表达式可能会影响性能本文的主要目的是了解一种使用正则化判断日期的方法。如果您想要一种可靠且快速的方法来验证日期,请考虑使用Java8提供的LocalDate.parse()。4.总结在本文中,我们从格式、范围和月份长度等规则中学习了使用正则表达式来匹配公历日期。
