年月日-正则

PS:学了正则表达式那么久,也没做出什么像样的模式出来,早上一觉醒来突发奇想,下定决心要证明一下咱正则可不是白学的——于是选择了最常见的日期匹配……

日期格式:年-月-日,即yyyy-mm-dd,如今天的日期为2008-11-1,当然按照yyyy-mm-dd的模式就是2008-11-01。我们的表达式应该同时匹配这两种日期——月、日为个位数的时候,前边的‘0’可有可无。

再有的一点,估计我们匹配万年历的机会不是太多,一般情况下,小打小闹,匹配个生辰八字,起始、终止日期就够了,于是我的表达式只匹配1900-2099——估计就我一般年龄的人是很难超越这两个年份的吧……

废话少说,开始写表达式吧。

首先当然是年份了——/((19|20)\d{2})/。(这里用了Perl的写法,由于Javascript沿用了此法,而且这种方法确实很简洁,所以我个人非常喜欢。)

匹配年份是整个表达式中最简单的部分,以下建立月和日的表达式可能出现多种情况,我只能在整个表达式中建立多种模式以供匹配的时候选择,在这些模式中,年份的部分基本上是一样的(除了闰年)。

小学生都知道的一件事:一年的12个月里,1、3、5、7、8、10、12月份中每月有31天,4、6、9、11月份中每月有30天,而2月最特殊,2月份只有28天而且闰年的时候是29天——对于闰年,我们等处理完一般情况再考虑特殊处理。

31天的月份——/(0?[13578]|1[02])/。

日期——/(0?[1-9]|[12]\d|3[01])/。

1. 综上,匹配31天的月份模式为:/(年)-(月)-(日)/,即/((19|20)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01])/

30天的月份——/(0?[469]|11)/。

日期——/(0?[1-9]|[12]\d|30)/。

2. 综上,匹配30天的月份模式为:/(年)-(月)-(日)/,即/((19|20)\d{2})-(0?[469]|11)-(0?[1-9]|[12]\d|30)/

以下匹配一般年份的2月,即28天的2月。

月份——/0?2/

日期——/(0?[1-9]|1\d|2[0-8])/

3. 综上,匹配28天的2月模式为:/(年)-(月)-(日)/,即/((19|20)\d{2})-0?2-(0?[1-9]|1\d|2[0-8])/

综合1、2、3,可建立匹配除了闰年之外的日期即——
/((31天的月份)|(30天的月份)|(28天的2月))/,即——
/((((19|20)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((19|20)\d{2})-(0?[469]|11)-(0?[1-9]|[12]\d|30))|(((19|20)\d{2})-0?2-(0?[1-9]|1\d|2[0-8])))/

到了这一步,我们要开始考虑闰年的2月了,我们都知道闰年的2月有29天,但到底什么才是闰年呢??

我们先花点时间列举出1900-2099之间,那些年份是闰年吧

1904,1908,1912,1916,1920,1924,1928,1932,1936,1940,1944,1948,1952,1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004,2008,2012,2016,2020,2024,2028,2032,2036,2040,2044,2048,2052,2056,2060,2064,2068,2072,2076,2080,2084,2088,2092,2096

闰年:能够被4整除,若是整百年还必须被400整除,如1900是整百年但不能被400整除所以不是闰年,而2000年是闰年。

或许我们都知道闰年该怎么算,但是正则表达式不知道,正则表达式内部是没有计算能力的,我们所能做的就是替它找出一个能够在有限次内列举出所有可能的解决方案——所以,以上我列举出所有的闰年并不是吃饱了撑着,而是为了替表达式找出规律……

认真分析以上闰年之后,很容易发现:
1. 个位数必是偶数
2. 十位数为奇数时,个位数只有两种可能:2和6
3. 十位数为偶数(除0外)时,个位数有三种可能:0、4、8
4. 十位数为0时,个位数为4和8,2000年特殊处理

所以,匹配闰年年份如下:/(((19|20)([13579][26]|[2468][048]|0[48]))|(2000))/

所以,闰年2月分的匹配模式为/(((19|20)([13579][26]|[2468][048]|0[48]))|(2000))-0?2-(0?[1-9]|[12]\d)/

综合前面的所有模式,即可得出匹配日期的正则表达式了
/^((((19|20)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((19|20)\d{2})-(0?[469]|11)-(0?[1-9]|[12]\d|30))|(((19|20)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|((((19|20)([13579][26]|[2468][048]|0[48]))|(2000))-0?2-(0?[1-9]|[12]\d)))$/

以上表达式并不是最优的,至少以下的方式会比较优良:
/^((((19|20)\d{2})-(0?[13-9]|1[012])-(0?[1-9]|[12]\d|30))|(((19|20)\d{2})-(0?[13578]|1[02])-31)|(((19|20)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|((((19|20)([13579][26]|[2468][048]|0[48]))|(2000))-0?2-29))$/
该表达式的匹配规则(按以下序号为顺序):
1.匹配除了2月份之外的1-30日
2.若1无法匹配,则匹配1,3,5,7,8,10,12月份的31日
3.若2无法匹配,则匹配2月份的1-28日

时间: 2024-10-09 19:40:54

年月日-正则的相关文章

用正则匹配年月日数据

/^(\d{4})-(\d{2})-(\d{2})/.exec("2023-08-17 16:44:17")["2023-08-17", "2023", "08", "17"]/(\d{4})-(\d{2})-(\d{2})/.exec("2023-08-17 16:44:17")["2023-08-17", "2023", "08&qu

正则大全

正则表达大全 $ 匹配行结束符.例如正则表达式weasel$ 能够匹配字符串"He's a weasel"的末尾,但是不能匹配字符串"They are a bunch of weasels.". ^ 匹配一行的开始.例如正则表达式^When in能够匹配字符串"When in the course of human events"的开始,但是不能匹配"What and When in the". * 匹配0或多个正好在它之前的

判断身份证: 要么是 15 位, 要么是 18 位, 最后一位可以 为字母, 并写程序提出其中的年月日。

答: 我们可以用正则表达式来定义复杂的字符串格式, (\d{17}[0-9a-zA-Z]|\d{14}[0-9a-zA-Z])可以用来判断是否为合法的 15 位或 18 位身份证号码.因为 15 位和 18 位的身份证号码都是从 7 位到第 12 位为身份证为日期类型.这样我们可以设计出更精确的正则模式, 使身份证号的日期合法, 这样我们的正则模式可以进一步将日期部分的正则修改为[12][0-9]{3}[01][0-9][123][0-9], 当然可以更精确的设置日期.在 jdk 的 java.

android经常使用正则工具类

此类提供日常开发中经常使用的正则验证函数.比方:邮箱.手机号.电话号码.身份证号码.日期.数字.小数.URL.IP地址等.使用Pattern对象的matches方法进行整个字符匹配,调用该方法相当于: Pattern p = Pattern.compile(regex); Matcher m = p.matcher(input); return m.matches(); 每一个正则可能还有待优化的地方,您如有更好的方式实现某一个功能的验证,欢迎提出来大家一起讨论. 以下是工具类的完整代码: 源代

js 验证正则

字符 含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个单词的边界. -或- 对正则表达式功能字符的还原,如"*"匹配它前面元字符0次或多次,/a*/将匹配a,aa,aaa,加了"\"后,/a\*/将只匹配"a*". ^ 匹配一个输入或一行的开头,/^a/匹配"an A",而不匹配"An a&quo

iOS开发实用技巧—身份证的正则校验

iOS开发实用技巧—身份证的正则校验 说明: 在ios项目的开发中可能很多地方都需要用到身份证校验,一般在开发的时候很多人都是直接百度去网上荡相关的正则表达式和校验代码,但是网上疯狂粘贴复制的校验代码本身也可能并不准确,可能会有风险,比如2013年1月1号起停止使用15位的身份证,网上的身份证校验普遍支持15位的号码. 在开发过程中,进行类似处理的时候,还是需要一些甄别的能力的,当然也要考虑自己的项目的实际情况.该文贴出了最近项目中使用到得身份证校验代码,以方便有需要的人“谨慎”获取. 一.规则

Android常用正则工具类

此类提供日常开发中常用的正则验证函数,比如:邮箱.手机号.电话号码.身份证号码.日期.数字.小数.URL.IP地址等.使用Pattern对象的matches方法进行整个字符匹配,调用该方法相当于:        Pattern p = Pattern.compile(regex);        Matcher m = p.matcher(input);        return m.matches();每个正则可能还有待优化的地方,您如有更好的方式实现某一个功能的验证,欢迎提出来大家一起讨论

iOS—身份证的正则校验

iOS—身份证的正则校验 说明: 在ios项目的开发中可能很多地方都需要用到身份证校验,一般在开发的时候很多人都是直接百度去网上荡相关的正则表达式和校验代码,但是网上疯狂 粘贴复制的校验代码本身也可能并不准确,可能会有风险,比如2013年1月1号起停止使用15位的身份证,网上的身份证校验普遍支持15位的号码. 在开发过程中,进行类似处理的时候,还是需要一些甄别的能力的,当然也要考虑自己的项目的实际情况.该文贴出了最近项目中使用到得身份证校验代码,以方便有需要的人“谨慎”获取. 一.规则 下面是i

正则大全(转)

$ 匹配行结束符.例如正则表达式weasel$ 能够匹配字符串"He's a weasel"的末尾,但是不能匹配字符串"They are a bunch of weasels.". ^ 匹配一行的开始.例如正则表达式^When in能够匹配字符串"When in the course of human events"的开始,但是不能匹配"What and When in the". * 匹配0或多个正好在它之前的那个字符.例如