我正在制作一个应该与月日格雷戈日期(javascript)相匹配的正则表达式,它适用于1月,3月,5月,7月,8月,10月和12月(31天的月份) )约会,但由于某些我无法弄清楚的原因,它不会与任何其他月份的任何日期相匹配。
对以下代码的一点解释:我将其设置为首次匹配日期的月 - 日部分,因此例如在2月31日它不匹配。所以,我目前已经匹配(((一个31天的月份)THEN(一个非字母数字字符,已捕获)然后(从1到31的一天))或((28天一个月)然后(非字母数字字符,捕获)然后(从1到29的一天))或((30天一个月)那么(一个非字母数字字符,捕获)然后(从1到30的一天)))然后(之前捕获)那个(AD过去或当年)。
我确信这个问题很简单,但我只是没有看到它。
^
(?:
(?:
(?: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])
$
答案 0 :(得分:2)
您收到此错误是因为您使用的\1
与最后2次更改不匹配。 \1
指的是第一个 ([^\dA-Za-z])
- 如果它不匹配,则无法进入年份。
一个简单的替代方案是(?:\1|\2|\3)
。
另一种选择是在模式(?=\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])
$
旁注: yikes!试试Datejs - 一个令人印象深刻的开源JavaScript日期库。
答案 1 :(得分:1)
您的问题是\1
反向引用。它指的是您第一次轮换中的([^\dA-Za-z])
组匹配(31天 - 月)。要匹配第二个轮换的分隔符,您需要\2
等。
因此,您可能希望使用(?:\1|\2|\3)
而不是\1
,除非在JavaScript中也出现错误。
最后,你知道这还没有正确验证日期吗?想想闰年......