php正则表达式 匹配日期,正则表达式-正则表达式以匹配有效日期

我登陆这里是因为这个问题的标题很宽泛,我一直在寻找可用于匹配特定日期格式(例如OP)的正则表达式。 但是我随后发现,正如许多答案和评论已全面突出显示的那样,在提取与质量低劣或非结构化源数据混在一起的日期时,存在许多陷阱使构建有效模式变得非常棘手。

在探索问题时,我想出了一个系统,使您可以通过将四个在分隔符上匹配的更简单的子表达式以及顺序中的年,月和日字段的有效范围排列在一起,来构建正则表达式 您需要。

这些是 :-

定界符

[^\w\d\r\n:]

这将匹配不是单词字符,数字字符,回车符,换行符或冒号的任何内容。 冒号必须存在,以防止在日期类似的时间匹配(请参阅我的测试数据)

您可以优化模式的这一部分以加快匹配速度,但这是检测大多数有效定界符的良好基础。

注意; 它将匹配带有混合定界符(例如2 / 12-73)的字符串,该定界符可能实际上不是有效日期。

年值

(\d{4}|\d{2})

这与两位或四位数字匹配,在大多数情况下是可以接受的,但是如果您要处理的是0-999年或9999年以后的数据,则需要决定如何处理,因为在大多数情况下为1,3 或> 4位数字的年份是垃圾。

月值

(0?[1-9]|1[0-2])

匹配1到12之间的任何数字,带或不带前导零-注意:0和00不匹配。

日期值

(0?[1-9]|[12]\d|30|31)

匹配1到31之间的任何数字,带或不带前导零-注意:0和00不匹配。

此表达式匹配日期,月份,年份格式的日期

(0?[1-9]|[12]\d|30|31)[^\w\d\r\n:](0?[1-9]|1[0-2])[^\w\d\r\n:](\d{4}|\d{2})

但它也可以匹配某些年,月日期。 还应与边界运算符一起进行预订,以确保选择了整个日期字符串,并防止从格式不正确的数据(即没有边界标签的数据中提取有效的子日期)匹配20/12/194和20/12/19以及 101/12/1974比赛为01/12/1974

将下一个表达式的结果与上一个表达式的结果与废话部分中的测试数据进行比较(如下)

\b(0?[1-9]|[12]\d|30|31)[^\w\d\r\n:](0?[1-9]|1[0-2])[^\w\d\r\n:](\d{4}|\d{2})\b

此正则表达式没有验证,因此将匹配格式正确但无效的日期(例如31/02/2001)。 那是一个数据质量问题,正如其他人所说的,您的正则表达式不需要验证数据。

因为您(作为开发人员)不能保证源数据的质量,所以您确实需要执行和处理代码中的其他验证,因此,如果尝试匹配和验证RegEx中的数据,它将变得非常混乱,并且变得很难 没有非常简洁的文档支持。

垃圾进垃圾出。

话虽如此,如果您确实有日期值各不相同的混合格式,则必须尽可能地提取; 您可以像这样将两个表达式组合在一起;

此(灾难性)表达式匹配DMY和YMD日期

(\b(0?[1-9]|[12]\d|30|31)[^\w\d\r\n:](0?[1-9]|1[0-2])[^\w\d\r\n:](\d{4}|\d{2})\b)|(\b(0?[1-9]|1[0-2])[^\w\d\r\n:](0?[1-9]|[12]\d|30|31)[^\w\d\r\n:](\d{4}|\d{2})\b)

但是您将无法确定1973年6月9日这样的日期是9月6日还是6月9日。 我正在努力思考这样一种情况,即该情况不会在某个地方造成问题,这是不好的做法,您不必这样处理-找到数据所有者并用治理锤来打击他们 。

最后,如果要匹配不带分隔符的YYYYMMDD字符串,则可以消除一些不确定性,表达式如下所示

\b(\d{4})(0[1-9]|1[0-2])(0[1-9]|[12]\d|30|31)\b

但请再次注意,它将匹配格式正确但无效的值,例如20010231(2月31日!):)

测试数据

在对该线程中的解决方案进行实验时,我最终得到了一个测试数据集,其中包含各种有效和无效日期,以及一些您可能希望或不希望匹配的棘手情况,例如,可以匹配为日期和日期的时间 多行。

我希望这对某人有用。

Valid Dates in various formats

Day, month, year

2/11/73

02/11/1973

2/1/73

02/01/73

31/1/1973

02/1/1973

31.1.2011

31-1-2001

29/2/1973

29/02/1976

03/06/2010

12/6/90

month, day, year

02/24/1975

06/19/66

03.31.1991

2.29.2003

02-29-55

03-13-55

03-13-1955

12\24\1974

12\30\1974

1\31\1974

03/31/2001

01/21/2001

12/13/2001

Match both DMY and MDY

12/12/1978

6/6/78

06/6/1978

6/06/1978

using whitespace as a delimiter

13 11 2001

11 13 2001

11 13 01

13 11 01

1 1 01

1 1 2001

Year Month Day order

76/02/02

1976/02/29

1976/2/13

76/09/31

YYYYMMDD sortable format

19741213

19750101

Valid dates before Epoch

12/1/10

12/01/660

12/01/00

12/01/0000

Valid date after 2038

01/01/2039

01/01/39

Valid date beyond the year 9999

01/01/10000

Dates with leading or trailing characters

12/31/21/

31/12/1921AD

31/12/1921.10:55

12/10/2016 8:26:00.39

wfuwdf12/11/74iuhwf

fwefew13/11/1974

01/12/1974vdwdfwe

01/01/99werwer

12321301/01/99

Times that look like dates

12:13:56

13:12:01

1:12:01PM

1:12:01 AM

Dates that runs across two lines

1/12/19

74

01/12/19

74/13/1946

31/12/20

08:13

Invalid, corrupted or nonsense dates

0/1/2001

1/0/2001

00/01/2100

01/0/2001

0101/2001

01/131/2001

31/31/2001

101/12/1974

56/56/56

00/00/0000

0/0/1999

12/01/0

12/10/-100

74/2/29

12/32/45

20/12/194

2/12-73

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值