regex для проверки даты в DD.Формат MM

Я погуглил много regexes, чтобы проверить даты в DD.MM.YYYY. Как этот:

(0[1-9]|1[0-9]|2[0-8]|(?:29|30)(?!.02)|29(?=.02.dd(?:[02468][048]|[13579][26]))|31(?=.0[13578]|.1[02]))(?:.(?=dd.)|-(?=dd-)|/(?=dd/))(0[1-9]|1[0-2])[./-]([1-9][0-9]{3})

и это прекрасно работает.

Насколько я понимаю([1-9][0-9]{3}), часть относится к году. Я попытался удалить его, и он начал проверять даты, заканчивающиеся точками, например01.05., 10.07.и т. д.

>>> regex = '^(0[1-9]|1[0-9]|2[0-8]|(?:29|30)(?!.02)|29(?=.02.dd(?:[02468][048]|[13579][26]))|31(?=.0[13578]|.1[02]))(?:.(?=dd.)|-(?=dd-)|/(?=dd/))(0[1-9]|1[0-2])[./-]$'
>>> aaa = '12.02.'
>>> bbb = '32.02.'
>>> print(re.match(regex, aaa))
<_sre.SRE_Match object; span=(0, 6), match='12.02.'>
>>> print(re.match(regex, bbb))
None

Но когда я удаляю часть, которая заботится о делителе точки / тире

[./-]

он не проверяет даты без конечных точек:

>>> regex = '^(0[1-9]|1[0-9]|2[0-8]|(?:29|30)(?!.02)|29(?=.02.dd(?:[02468][048]|[13579][26]))|31(?=.0[13578]|.1[02]))(?:.(?=dd.)|-(?=dd-)|/(?=dd/))(0[1-9]|1[0-2])$'
>>> aaa = '12.02'
>>> bbb = '32.02'
>>> print(re.match(regex, aaa))
None
>>> print(re.match(regex, bbb))
None

Как это сделать?

ОБНОВЛЕНИЕ О FEB 28 / FEB 29:

Это нормально, если это не подтвердит 28/29 февраля, это приемлемо в моем случае.

ОБНОВЛЕНИЕ О PYTHON:

Я не могу использовать проверку python для этого, к сожалению, это только поле regex в веб-форме, которую я могу использовать.

2 ответа

  1. Решение

     ^(0[1-9]|[12][0-9]|30(?!\.02)|31(?!\.(0[2469]|11)))\.(0[1-9]|1[0-2])$
    

    Пример в python

    >>> daymonth_match = r"^(0[1-9]|[12][0-9]|30(?!\.02)|31(?!\.(0[2469]|11)))\.(0[1-9]|1[0-2])$"
    >>> print re.match(daymonth_match, "12.04")
    <_sre.SRE_Match object at 0x7f3728125880>
    >>> print re.match(daymonth_match, "29.02")
    <_sre.SRE_Match object at 0x7f3728125880>
    >>> print re.match(daymonth_match, "30.02")
    None
    >>> print re.match(daymonth_match, "30.04")
    <_sre.SRE_Match object at 0x7f3728125880>
    >>> print re.match(daymonth_match, "31.04")
    None
    >>> print re.match(daymonth_match, "31.05")
    <_sre.SRE_Match object at 0x7f3728125880>
    

    Он предполагает 29.02всегда действительным.

    Некоторые детали о том, как это работает

    Это регулярное выражение полагается на отрицательное утверждение lookahead (?!...).
    Например, выражение 30(?!\.02)означает, что 30оно совпадает только в том случае, если за ним не следует \.02и, поскольку это «взгляд вперед», \.02не рассматривается как совпадение самого выражения (Подробнее см. документацию python)