为什么我的日期验证regex不承认二月(以及其他)?

时间:2021-04-10 02:29:11

I'm working on a regex that's supposed to match month-day-year gregorian dates (in javascript), and it works fine for January, March, May, July, August, October, and December (31-day months) dates, but for some reason which I haven't been able to figure out, it will not match any date from any other month.

我工作在一个正则表达式的匹配月公历日期(在javascript),它工作正常1月,3月,5月,7月,8月,10月和12月(31天个月)日期,但出于某种原因,我一直没能弄明白,它不会匹配任何日期从任何其他。

A little explanation of the code below: I've set it up to first match the month-day part of the date all at once, so it doesn't match on February 31st, for example. So, I currently have it matching (((a 31-day month) THEN (a non-alphanumeric character, captured) THEN (a day from 1 through 31)) OR ((a 28-day month) THEN (a non-alphanumeric character, captured) THEN (a day from 1 through 29)) OR ((a 30-day month) THEN (a non-alphanumeric character, captured) THEN (a day from 1 through 30))) THEN (the previously captured character) THEN (a past or current year AD).

下面代码的一个小解释是:我将它设置为第一次匹配日期的月份部分,所以它不会在2月31日匹配。所以,我目前有匹配(((一个月31天),那么(非字母数字字符,捕获),那么(从1到31)一天)或((28天)(一个非字母数字字符,捕获)然后(从1到29)一天)或(30天(一个月),那么(非字母数字字符,捕获),那么(从1到30天)))(前面捕获的字符)然后(过去或当前年度广告)。

I'm sure the problem is simple, but I'm just not seeing it.

我肯定问题很简单,但我就是看不见。

^
(?:
  (?:
    (?:0?[13578]|1[02])
    ([^\dA-Za-z])
    (?:0?[1-9]|1[0-9]|2[0-9]|3[01])
  )
  |
  (?:
    (?:0?2)
    ([^\dA-Za-z])
    (?:0?[1-9]|1[0-9]|2[0-9])
  )
  |
  (?:
    (?:0?[469]|11)
    ([^\dA-Za-z])
    (?:0?[1-9]|1[0-9]|2[0-9]|30)
  )
)
\1
(?:0{0,3}[1-9]|0{0,2}[1-9][0-9]|0?[1-9][0-9]{2}|1[0-9]{3}|200[0-9]|201[01])
$

2 个解决方案

#1


2  

You get this error because you're using \1, which doesn't match for the last 2 alternations. \1 refers to the first ([^\dA-Za-z]) - if it didn't match, it cannot get to the year.

你会得到这个错误,因为你使用的是\1,它与最后两个交替不匹配。\ 1指的是第一个([^ \ dA-Za-z])——如果不匹配,无法到达。

A simple alternative is (?:\1|\2|\3).

一个简单的选择是(?:\1|\2|\3)。

Another option is to add at the start of the pattern (?=\d+([^\dA-Za-z])), and use \1 on all places. For example:

另一种选择是增加的模式(? = \ d +([^ \ dA-Za-z])),并使用\ 1在所有地方。例如:

^
(?=\d+([^\dA-Za-z]))   # capture the separator as \1
(?:
  (?:
    (?:0?[13578]|1[02])
    \1
    (?:0?[1-9]|1[0-9]|2[0-9]|3[01])
  )
  |
  (?:
    (?:0?2)
    \1
    (?:0?[1-9]|1[0-9]|2[0-9])
  )
  |
  (?:
    (?:0?[469]|11)
    \1
    (?:0?[1-9]|1[0-9]|2[0-9]|30)
  )
)
\1
(?:0{0,3}[1-9]|0{0,2}[1-9][0-9]|0?[1-9][0-9]{2}|1[0-9]{3}|200[0-9]|201[01])
$

On a side note: yikes! try Datejs - an impressive open-source JavaScript date library.

附带说明:哎呀!试试Datejs——一个令人印象深刻的开源JavaScript数据库。

#2


1  

Your problem is the \1 backreference. It refers back to what the ([^\dA-Za-z]) group in your first alternation matches (31-day-months). To match the delimiter of the second alternation, you'd need \2 etc.

你的问题是\1反向引用。文中引用了什么([^ \ dA-Za-z])组在第一个交替匹配(31-day-months)。要匹配第二种交替的分隔符,需要使用\2等。

So perhaps you might want to use (?:\1|\2|\3) instead of \1, unless that gives an error, too, in JavaScript.

因此,您可能想要使用(?:\1|\2|\3)而不是\1,除非这在JavaScript中也会产生错误。

Finally, you're aware that this still isn't validating dates correctly? Think about leap years...

最后,您知道这仍然不能正确地验证日期吗?考虑闰年……

#1


2  

You get this error because you're using \1, which doesn't match for the last 2 alternations. \1 refers to the first ([^\dA-Za-z]) - if it didn't match, it cannot get to the year.

你会得到这个错误,因为你使用的是\1,它与最后两个交替不匹配。\ 1指的是第一个([^ \ dA-Za-z])——如果不匹配,无法到达。

A simple alternative is (?:\1|\2|\3).

一个简单的选择是(?:\1|\2|\3)。

Another option is to add at the start of the pattern (?=\d+([^\dA-Za-z])), and use \1 on all places. For example:

另一种选择是增加的模式(? = \ d +([^ \ dA-Za-z])),并使用\ 1在所有地方。例如:

^
(?=\d+([^\dA-Za-z]))   # capture the separator as \1
(?:
  (?:
    (?:0?[13578]|1[02])
    \1
    (?:0?[1-9]|1[0-9]|2[0-9]|3[01])
  )
  |
  (?:
    (?:0?2)
    \1
    (?:0?[1-9]|1[0-9]|2[0-9])
  )
  |
  (?:
    (?:0?[469]|11)
    \1
    (?:0?[1-9]|1[0-9]|2[0-9]|30)
  )
)
\1
(?:0{0,3}[1-9]|0{0,2}[1-9][0-9]|0?[1-9][0-9]{2}|1[0-9]{3}|200[0-9]|201[01])
$

On a side note: yikes! try Datejs - an impressive open-source JavaScript date library.

附带说明:哎呀!试试Datejs——一个令人印象深刻的开源JavaScript数据库。

#2


1  

Your problem is the \1 backreference. It refers back to what the ([^\dA-Za-z]) group in your first alternation matches (31-day-months). To match the delimiter of the second alternation, you'd need \2 etc.

你的问题是\1反向引用。文中引用了什么([^ \ dA-Za-z])组在第一个交替匹配(31-day-months)。要匹配第二种交替的分隔符,需要使用\2等。

So perhaps you might want to use (?:\1|\2|\3) instead of \1, unless that gives an error, too, in JavaScript.

因此,您可能想要使用(?:\1|\2|\3)而不是\1,除非这在JavaScript中也会产生错误。

Finally, you're aware that this still isn't validating dates correctly? Think about leap years...

最后,您知道这仍然不能正确地验证日期吗?考虑闰年……