关于java:Java中使用正则检查有效日期

一、介绍

正则表达式可用于匹配各种模式,本文将用java中的正则来检测给定字符串是否饮蕴含无效日期

二、日期格局概述

先对公历中一个无效日期做一个定义,日期格局咱们个别定义为yyyy-MM-dd。思考范畴大小年、平年等状况,先说平年。
一般平年:公历年份是4的倍数,且不是100的倍数的,为平年(如2004年、2020年等就是平年)。
世纪平年:公历年份是整百数的,必须是400的倍数才是平年(如1900年不是平年,2000年是平年)。
无效日期举例:

  • 2017-12-31
  • 2020-02-29
  • 2400-02-29

有效日期举例

  • 2017/12/31: 宰割符不正确
  • 2018-1-1: 没有前导0
  • 2018-04-31: 天数不正确
  • 2100-02-29: 平年2月只有28天

    三、实现

    咱们要用正则匹配日期,首先先定义一个接口DateMatcher,只提供一个匹配办法

public interface DateMatcher {
    boolean matches(String date);
}

上面逐渐介绍实现,构建一个残缺解决方案

3.1 匹配数字

创立一个简略的正则来对字符串进行格局束缚:

public class FormattedDateMatcher implements DateMatcher {
    private static final Pattern DATE_PATTERN = 
        Pattern.compile("^\\d{2}-\\d{4}-\\d{2}$");

    @Override
    public boolean matches(String date) {
        return DATE_PATTERN.matcher(date).matches();
    }
}

这里咱们指定了一个无效日期必须由三组中划线宰割的整数组成,第一组由4个整数,其余两组各有两个整数。
举例:
匹配的日期: 2017-12-31, 2018-01-31, 0000-00-00, 1029-00-72
不匹配的日期:2018-01, 2018-01-XX, 2020/02/09

3.2 匹配日期的范畴

当初咱们胜利匹配了个别日期格局,当初咱们做进一步束缚,咱们将年份限定在1900-2999,月份和日期也做同样的束缚

^((19|2[0-9])[0-9]{2})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$

这里咱们对三组整数范畴做了束缚

  • ((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-XX

3.3 匹配2月29

为了匹配2月29,首先要判断平年,把1900-2099之间的平年匹配进去。如果一个数的后2位能被4整除则原数也能被4整除;如果后两位是00,这个数能被100整除

^((2000|2400|2800|(19|2[0-9])(0[48]|[2468][048]|[13579][26]))-02-29)$

这个正则由以下局部组成

  • 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/29

3.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/28

3.5. Matching 31-Day Months

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/31

3.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/30

3.7 汇总的日期匹配器

当初咱们将下面的所有模式合并成一个匹配器满足所有的日期束缚

class GregorianDateMatcher implements DateMatcher {

    private static Pattern 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))$");

    @Override
    public boolean matches(String date) {
        return DATE_PATTERN.matcher(date).matches();
    }
}

咱们应用了”|”来匹配28天的、29天的、30天的、31天的,此时咱们曾经满足了开始介绍的日期的所有束缚

3.8 性能阐明

解析简单的表达式可能会影响性能。本文的次要目标次要是理解用正则来判断日期的一种思路,如果要一种牢靠且疾速的办法来验证日期,请思考应用Java8提供的LocalDate.parse()。

四、总结

本文咱们学习了应用正则表达式从格局、范畴和月份长度等规定匹配公历日期。

【腾讯云】云产品限时秒杀,爆款1核2G云服务器,首年50元

阿里云限时活动-2核2G-5M带宽-60G SSD-1000G月流量 ,特惠价99元/年(原价1234.2元/年,可以直接买3年),速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表评论

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据