ISO 8601 正则表达式

15 篇文章 0 订阅
6 篇文章 0 订阅

这个正则是从网上抄了以后修改的,具体网址记不清了,修改内容如下:

  • 它原来简写\d用[0-9]代替,建议大家写正则如非必要不要用简写.
  • 修改年月日部份分组(用括号分组)为以下格式以方便程序解析.

    “年月日完整格式”+“完整年份” + “年前二位” + “年后二位” + “月” + "天"共6个字段,如下:
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('2010-3-23','(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[13578]|1[02])-(0?[1-9]|[12][0-9]|3[01]))') as f
union all
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('2010-11-23','(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[469]|11)-(0?[1-9]|[12][0-9]|30))') as f
union all
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('2010-2-28','(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?2)-(0?[1-9]|1[0-9]|2[0-8]))') as f
union all
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('2012-2-29','(((1[6-9]|[2-9][0-9])([13579][26]))-(0?2)-(29))') as f
union all
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('2020-2-29','(((1[6-9]|[2-9][0-9])([2468][048]))-(0?2)-(29))') as f
union all
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('2004-2-29','(((1[6-9]|[2-9][0-9])(0[48]))-(0?2)-(29))') as f
union all
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('3600-2-29','((([13579]6)(00))-(0?2)-(29))') as f
union all
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('2000-2-29','((([2468][048])(00))-(0?2)-(29))') as f
union all
select f[1],f[2],f[3],f[4],f[5],f[6] 
from regexp_matches('3200-2-29','((([3579]2)(00))-(0?2)-(29))') as f

完整正则表达式

^(((((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[13578]|1[02])-(0?[1-9]|[12][0-9]|3[01]))|(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[469]|11)-(0?[1-9]|[12][0-9]|30))|(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?2)-(0?[1-9]|1[0-9]|2[0-8]))|(((1[6-9]|[2-9][0-9])([13579][26]))-(0?2)-(29))|(((1[6-9]|[2-9][0-9])([2468][048]))-(0?2)-(29))|(((1[6-9]|[2-9][0-9])(0[48]))-(0?2)-(29))|((([13579]6)(00))-(0?2)-(29))|((([2468][048])(00))-(0?2)-(29))|((([3579]2)(00))-(0?2)-(29)))T((([0-1][0-9])|([2][0-4])):(([0-5])([0-9])):(([0-5])([0-9]))))$

虽然看起来很复杂,但是我们可以分解开来看问题就简单了.这里建议用Notepad++以方便查看括号对,Notepad一组括号可以标红.

分解正则表达式

^(
(
(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[13578]|1[02])-(0?[1-9]|[12][0-9]|3[01]))|
(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[469]|11)-(0?[1-9]|[12][0-9]|30))|
(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?2)-(0?[1-9]|1[0-9]|2[0-8]))|
(((1[6-9]|[2-9][0-9])([13579][26]))-(0?2)-(29))|
(((1[6-9]|[2-9][0-9])([2468][048]))-(0?2)-(29))|
(((1[6-9]|[2-9][0-9])(0[48]))-(0?2)-(29))|
((([13579]6)(00))-(0?2)-(29))|
((([2468][048])(00))-(0?2)-(29))|
((([3579]2)(00))-(0?2)-(29))
)
T(
(([0-1][0-9])|([2][0-4]))
:(([0-5])([0-9]))
:(([0-5])([0-9]))
)
)$
select f from regexp_matches('2019-12-31T12:19:24','^(((((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[13578]|1[02])-(0?[1-9]|[12][0-9]|3[01]))|(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[469]|11)-(0?[1-9]|[12][0-9]|30))|(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?2)-(0?[1-9]|1[0-9]|2[0-8]))|(((1[6-9]|[2-9][0-9])([13579][26]))-(0?2)-(29))|(((1[6-9]|[2-9][0-9])([2468][048]))-(0?2)-(29))|(((1[6-9]|[2-9][0-9])(0[48]))-(0?2)-(29))|((([13579]6)(00))-(0?2)-(29))|((([2468][048])(00))-(0?2)-(29))|((([3579]2)(00))-(0?2)-(29)))T((([0-1][0-9])|([2][0-4])):(([0-5])([0-9])):(([0-5])([0-9]))))$') as f

年部份

((1[6-9]|[2-9][0-9])([0-9]{2}))
(1[6-9]|[2-9][0-9]) #表示日期开头必须为16-19或者20-99
([0-9]{2})  #表示范围为00-99
#组合起来日期范围就是1600-9999年

月部份

(0?[13578]|1[02]) #表示只允许为01/03/05/07/08(其中0可填或不填)或10/12
(0?[469]|11)  #表示只允许为04/06/09(其中0可填或不填)或11
(0?2) #表示只允许为02(其中0可填或不填)

月天部分

#0?[1-9]表示01/02/03/04/05/06/07/08/09.[12][0-9]同理范围为11-19或21-29
(0?[1-9]|[12][0-9]|3[01])	#表示1-31天
(0?[1-9]|[12][0-9]|30)	#表示1-30天
(0?[1-9]|1[0-9]|2[0-8])	#表示1-28天

小结

(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[13578]|1[02])-(0?[1-9]|[12][0-9]|3[01]))	#表示年范围为1600-9999,月范围为01/03/05/07/0810/12,月天范围为1-31天
(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[469]|11)-(0?[1-9]|[12][0-9]|30))	#表示年范围为1600-9999,月范围为04/06/09/11,月天范围为1-30天
(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?2)-(0?[1-9]|1[0-9]|2[0-8]))	#表示年范围为1600-9999,月范围为2,月天范围为1-28天.这里只判断了平年2月份的天数

判断具有29天的闰年

判断闰年还是平年,闰年一年有366天,平年一年有365天

遵循的规律为: 四年一闰,百年不闰,四百年再闰.

#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))

根据以上知识得知2月份比较特殊,平年有28天,闰年有29天,因此需要专门判断

(1[6-9]|[2-9][0-9]) #这部份知识前面已经计划过,因此这里用年份开头二位数用xx代替
(((1[6-9]|[2-9][0-9])([13579][26]))-(0?2)-29)	#表示xx12/xx16/xx32/xx36/xx52/xx56/xx72/xx76/xx92/xx96年的二月是闰年有29天(四年一闰).
(((1[6-9]|[2-9][0-9])([2468][048]))-(0?2)-29)	#表示xx20/xx24/xx28/xx40/xx44/xx48/xx60/xx64/xx68/xx80/xx84/xx88年的二月是闰年有29天(四年一闰).
(((1[6-9]|[2-9][0-9])(0[48]))-(0?2)-29)	#表示xx04/xx08年的二月是闰年有29天(四年一闰).
((([13579]6)00)-(0?2)-29)	#表示1600/3600/5600/7600/9600年的二月是闰年有29天(百年不闰,四百年再闰).
((([2468][048])00)-(0?2)-29)	#表示2000/2400/2800/4000/4400/4800/6000/6400/6800/8000/8400/8800年的二月是闰年有29天(百年不闰,四百年再闰).
((([3579]2)00)-(0?2)-29)	#表示3200/5200/7200/9200年的二月是闰年有29天(百年不闰,四百年再闰).

判断年月日完整正则

^((((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[13578]|1[02])-(0?[1-9]|[12][0-9]|3[01]))|(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[469]|11)-(0?[1-9]|[12][0-9]|30))|(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?2)-(0?[1-9]|1[0-9]|2[0-8]))|(((1[6-9]|[2-9][0-9])([13579][26]))-(0?2)-(29))|(((1[6-9]|[2-9][0-9])([2468][048]))-(0?2)-(29))|(((1[6-9]|[2-9][0-9])(0[48]))-(0?2)-(29))|((([13579]6)(00))-(0?2)-(29))|((([2468][048])(00))-(0?2)-(29))|((([3579]2)(00))-(0?2)-(29)))$

分解正则表达式

^(
(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[13578]|1[02])-(0?[1-9]|[12][0-9]|3[01]))|
(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[469]|11)-(0?[1-9]|[12][0-9]|30))|
(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?2)-(0?[1-9]|1[0-9]|2[0-8]))|
(((1[6-9]|[2-9][0-9])([13579][26]))-(0?2)-(29))|
(((1[6-9]|[2-9][0-9])([2468][048]))-(0?2)-(29))|
(((1[6-9]|[2-9][0-9])(0[48]))-(0?2)-(29))|
((([13579]6)(00))-(0?2)-(29))|
((([2468][048])(00))-(0?2)-(29))|
((([3579]2)(00))-(0?2)-(29))
)$
select f from regexp_matches('3200-2-29','^((((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[13578]|1[02])-(0?[1-9]|[12][0-9]|3[01]))|(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?[469]|11)-(0?[1-9]|[12][0-9]|30))|(((1[6-9]|[2-9][0-9])([0-9]{2}))-(0?2)-(0?[1-9]|1[0-9]|2[0-8]))|(((1[6-9]|[2-9][0-9])([13579][26]))-(0?2)-(29))|(((1[6-9]|[2-9][0-9])([2468][048]))-(0?2)-(29))|(((1[6-9]|[2-9][0-9])(0[48]))-(0?2)-(29))|((([13579]6)(00))-(0?2)-(29))|((([2468][048])(00))-(0?2)-(29))|((([3579]2)(00))-(0?2)-(29)))$') as f

时间部分

时间部分就比较简单了,其中小时范围为1-24,分钟和秒范围0-59)

^T((([0-1][0-9])|([2][0-4])):(([0-5])([0-9])):(([0-5])([0-9])))$

分解正则表达式

T(
(([0-1][0-9])|([2][0-4]))
:(([0-5])([0-9]))
:(([0-5])([0-9]))
)
select f from regexp_matches('T12:19:24','^(T((([0-1][0-9])|([2][0-4])):(([0-5])([0-9])):(([0-5])([0-9]))))$') as f
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kmblack1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值