Java中使用正则检查有效日期的实现

 更新时间:2023年10月11日 11:11:19   作者:okokabcd  
要判断一个字符串是否符合时间格式,可以使用正则表达式,本文主要介绍了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{4}-\\d{2}-\\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][0-9]|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()。

四、总结

本文我们学习了使用正则表达式从格式、范围和月份长度等规则匹配公历日期。

到此这篇关于Java中使用正则检查有效日期的实现的文章就介绍到这了,更多相关Java 正则有效日期内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一文搞懂hashCode()和equals()方法的原理

    一文搞懂hashCode()和equals()方法的原理

    这篇文章主要介绍了详解hashCode()和equals()的本质区别和联系,本文先对两种方法作了介绍,然后对二者联系进行分析,具有一定参考价值,需要的朋友可以了解下
    2020-06-06
  • 轻松掌握Java桥接模式

    轻松掌握Java桥接模式

    这篇文章主要帮助大家轻松掌握Java桥接模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • 详解Java设计模式之外观模式

    详解Java设计模式之外观模式

    在Java开发中,设计模式是一种十分常见的编程思想,它可以帮助我们解决很多实际开发中的问题,本篇文章将介绍一种常见的设计模式——外观模式,并结合实际的开发场景进行讲解,需要的朋友可以参考下
    2023-06-06
  • Spring中校验器(Validator)的深入讲解

    Spring中校验器(Validator)的深入讲解

    Spring校验器,参数校验从此简单。下面这篇文章主要给大家介绍了关于Spring中校验器(Validator)的相关资料,文中通过示例代码介绍非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-06-06
  • windows下java环境变量的设置方法

    windows下java环境变量的设置方法

    在“系统变量”中,设置3项属性,JAVA_HOME,PATH,CLASSPATH(大小写无所谓),若已存在则点击“编辑”,不存在则点击“新建”
    2013-09-09
  • 阿里云主机上安装jdk 某库出现问题的解决方法

    阿里云主机上安装jdk 某库出现问题的解决方法

    今天安装jdk到阿里云服务上,首先看下阿里云是32位还是64位的,如果是32位下载32位的包,如果是64位的下载64位的包,下面与大家分享下安装过程中遇到问题的解决方法
    2013-06-06
  • springboot 多数据源配置不生效遇到的坑及解决

    springboot 多数据源配置不生效遇到的坑及解决

    这篇文章主要介绍了springboot 多数据源配置不生效遇到的坑及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 一文带你剖析Redisson分布式锁的原理

    一文带你剖析Redisson分布式锁的原理

    相信使用过redis的,或者正在做分布式开发的童鞋都知道redisson组件,它的功能很多,但我们使用最频繁的应该还是它的分布式锁功能,少量的代码,却实现了加锁、锁续命(看门狗)、锁订阅、解锁、锁等待(自旋)等功能,我们来看看都是如何实现的
    2022-11-11
  • java中lambda表达式语法说明

    java中lambda表达式语法说明

    “Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
    2016-09-09
  • Java并发编程示例(十):线程组

    Java并发编程示例(十):线程组

    这篇文章主要介绍了Java并发编程示例(十):线程组,Java提供了ThreadGroup类来控制一个线程组,一个线程组可以通过线程对象来创建,也可以由其他线程组来创建,生成一个树形结构的线程,需要的朋友可以参考下
    2014-12-12

最新评论