Регулярное выражение для asp:RegularExpressionValidator в формате MMddyy (выпуск високосного года)

Нам нужна помощь для регулярного выражения, которое работает с asp.net asp:RegularExpressionValidator для проверки даты в формате MMddyy. Проблема, с которой мы сталкиваемся, это високосный год. Проблема заключается в том, что с помощью регулярного выражения можно проверить, что оно принимает только действительные даты високосного года, например, 29.02.2008 является действительной датой, а 29.02.2010 не является допустимой датой.

Любое регулярное выражение, которое работает с «asp:RegularExpressionValidator»?


person Malik    schedule 27.11.2010    source источник
comment
Это ммддгг или мм/дд/гг или мм/дд/гггг? Любые другие требования? Действительно ли 01.01.1792? Как насчет 09.09.99 или 09.09.9999? Если это ммдддй, то где граница между 1900-ми и 2000-ми?   -  person Tim Pietzcker    schedule 27.11.2010
comment
@Tim: Это мм/дд/гггг. Что касается действительности, я не думаю, что у нас есть какие-то конкретные требования. Нет отсечки. Я не думаю, что мы вдаемся в такие подробности :(. Должны ли мы?   -  person Malik    schedule 27.11.2010


Ответы (4)


Хорошо, вы просили регулярное выражение. Вот. Я думаю, сразу становится очевидным, почему не стоит проверять дату с помощью регулярного выражения:

Во-первых, подробная версия с комментариями, чтобы хотя бы сделать возможным понимание этого зверя:

^       # start of string
(?:     # either match...
 (?:
  (?:   # 31st day of all allowed months
   (?:(?:0?[13578]|1[02])/31)
   |    # or
   (?:(?:0?[13-9]|1[0-2])/(?:29|30))
  )     # 29th/30th day of any month except February
  /     # plus any year since 1600
  (?:1[6-9]|[2-9]\d)
  \d{2}
 )
|       # or
 (?:    # match Feb 29th
  0?2/29/
  (?:   # in all leap years since 1600
   (?:
    (?: # century
     1[6-9]|[2-9]\d
    )
    (?: # two-digit years divisible by four, not ending in 00
     0[48]
     |
     [2468][048]
     |
     [13579][26]
    )
    |
    (?: # all the leap years ending in 00
     (?:16|[2468][048]|[3579][26])
    00
    )
   )
  )
 )
|       # or
 (?:    # (for any month)
  (?:0?[1-9])
  |
  (?:1[0-2])
 )
 /
 (?:    # match the 1st-28th day
  0?[1-9]|1\d|2[0-8]
 )
 /
 (?:
  (?:1[6-9]|[2-9]\d)\d{2}
 )
)$

Или, если вы не можете использовать подробные регулярные выражения в валидаторах ASP.NET:

^(?:^(?:(?:(?:(?:(?:0?[13578]|1[02])/31)|(?:(?:0?[13-9]|1[0-2])/(?:29|30)))/(?:1[6-9]|[2-9]\d)\d{2})|(?:0?2/29/(?:(?:(?:1[6-9]|[2-9]\d)(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:(?:0?[1-9])|(?:1[0-2]))/(?:0?[1-9]|1\d|2[0-8])/(?:(?:1[6-9]|[2-9]\d)\d{2}))$)$

Они позволяют, но не требуют начального нуля в месяцах/днях, состоящих из одной цифры. Если вы этого не хотите, замените все экземпляры 0? на 0.

person Tim Pietzcker    schedule 27.11.2010
comment
+1 если получится! Я действительно надеюсь, что вы не просто написали это регулярное выражение, а сделали его ранее! - person El Ronnoco; 27.11.2010
comment
Я переработал старый, который я ранее адаптировал из найденного на regexlib.com. Я бы никогда не написал что-то подобное сам :) И да, это работает, по крайней мере, на моей машине (тм). - person Tim Pietzcker; 27.11.2010
comment
Спасибо большое за вашу помощь. Позвольте мне попробовать это :) - person Malik; 27.11.2010
comment
@FailedDev: Да, но разве это не ужасно? - person Tim Pietzcker; 18.11.2011
comment
@TimPietzcker Ну, это, конечно, не самый простой способ сделать это, однако иногда существуют ограничения, которые заставляют кого-то использовать только регулярное выражение. В данном случае это лучшее решение :) - person FailedDev; 18.11.2011
comment
Подождите, какие движки регулярных выражений допускают символы новой строки и пробелы? Это кажется таким большим благом для компоновки и удобочитаемости! - person wwaawaw; 07.10.2012
comment
@TimPietzcker ... не говоря уже о комментариях! - person wwaawaw; 07.10.2012
comment
@adlwalrus: почти все новые (Perl, PHP, Python, Java, Ruby, .NET, JGSoft...), за заметным исключением JavaScript. - person Tim Pietzcker; 07.10.2012
comment
заметно, к сожалению! как тогда получить фактическое пространство? \s? - person wwaawaw; 07.10.2012
comment
@adlwalrus: \s также соответствует другим пробелам, но [ ] или \ (не уверен, что пробел после обратной косой черты будет отображаться правильно) также работает в подробном режиме. - person Tim Pietzcker; 07.10.2012

Если серверная часть не подходит, вам придется использовать JavaScript. Попробуйте код, опубликованный и объясненный здесь. Он определяет, что 29.02.2010 недействительно, а 29.02.2008 верно. Используйте CustomValidator для вызова функции JavaScript, когда это необходимо.

person bitxwise    schedule 27.11.2010

Поскольку вам нужна логика для проверки високосных лет, рассмотрите возможность использования CustomValidator. Я собрал это относительно быстро, но, надеюсь, вы поняли идею.

protected void dateFormatValidator_ServerValidate(object source, ServerValidateEventArgs args)
{
    if (args.Value.Length == 6)
    {
        var month = args.Value.Substring(0, 2);
        var day = args.Value.Substring(2, 2);
        var year = args.Value.Substring(4, 2);

        DateTime dummyValue;
        args.IsValid = DateTime.TryParse(month + "/" + day + "/" + year, out dummyValue);
    }
    else
    {
        args.IsValid = false;
    }
}
person Phil Hunt    schedule 27.11.2010
comment
Большое спасибо за ваш ответ, но серверная часть не вариант :( - person Malik; 27.11.2010

Как побитово говорит, клиентский JS - это способ сделать это, а не ужасное регулярное выражение а-ля ошеломляющий пост Тома. У меня есть довольно аккуратный валидатор даты на моей рабочей машине, я опубликую в понедельник.

Если вы когда-нибудь столкнетесь с ошибкой проверки вашего приложения, можете ли вы представить себе кошмар, связанный с попыткой расшифровать это регулярное выражение?

person El Ronnoco    schedule 27.11.2010