Регулярное выражение для соответствия действительным датам - PullRequest
56 голосов
/ 09 сентября 2008

Я пытаюсь написать регулярное выражение, которое проверяет дату. Регулярное выражение должно соответствовать следующему

  • M / D / YYYY * * +1004
  • MM / DD / YYYY
  • Месяцы, состоящие из одной цифры, могут начинаться с нуля (например: 03/12/2008)
  • Дни с одной цифрой могут начинаться с нуля (например: 3/02/2008)
  • НЕ МОЖЕТ включать 30 февраля или 31 февраля (например, 31.02.2008)

Пока у меня есть

^(([1-9]|1[012])[-/.]([1-9]|[12][0-9]|3[01])[-/.](19|20)\d\d)|((1[012]|0[1-9])(3[01]|2\d|1\d|0[1-9])(19|20)\d\d)|((1[012]|0[1-9])[-/.](3[01]|2\d|1\d|0[1-9])[-/.](19|20)\d\d)$

Это соответствует должным образом, ЗА ИСКЛЮЧЕНИЕМ, которое все еще включает 30/02/2008 и 2/31/2008.

У кого-нибудь есть лучшее предложение?

Редактировать: Я нашел ответ на RegExLib

^((((0[13578])|([13578])|(1[02]))[\/](([1-9])|([0-2][0-9])|(3[01])))|(((0[469])|([469])|(11))[\/](([1-9])|([0-2][0-9])|(30)))|((2|02)[\/](([1-9])|([0-2][0-9]))))[\/]\d{4}$|^\d{4}$

Соответствует всем действительным месяцам, следующим за форматом MM / DD / YYYY.

Спасибо всем за помощь.

Ответы [ 15 ]

1 голос
/ 14 сентября 2008

Версия Perl 6

rx{
  ^

  $<month> = (\d ** 1..2)
  { $<month> <= 12 or fail }

  '/'

  $<day> = (\d ** 1..2)
  {
    given( +$<month> ){
      when 1|3|5|7|8|10|12 {
        $<day> <= 31 or fail
      }
      when 4|6|9|11 {
        $<day> <= 30 or fail
      }
      when 2 {
        $<day> <= 29 or fail
      }
      default { fail }
    }
  }

  '/'

  $<year> = (\d ** 4)

  $
}

После того, как вы используете это для проверки ввода, значения доступны в $/ или индивидуально как $<month>, $<day>, $<year>. (это просто синтаксис для доступа к значениям в $/)

Не предпринималось никаких попыток проверить год или указать, что он не соответствует 29 февраля в не високосные годы.

1 голос
/ 09 сентября 2008

Я знаю, что это не отвечает на ваш вопрос, но почему бы вам не использовать процедуру обработки даты, чтобы проверить, является ли она действительной датой? Даже если вы измените регулярное выражение с отрицательным прогнозным утверждением наподобие (?! 31/0? 2) (т. Е. Не совпадете с 31/2 или 31/02), у вас все равно будет проблема принятия 29 02 в не високосные годы и о формате с одним разделителем даты.

Проблема не простая, если вы действительно хотите проверить дату, проверьте эту ветку форума .

Для примера или лучшего способа, в C #, проверьте эту ссылку

Если вы используете другую платформу / язык, сообщите нам

1 голос
/ 09 сентября 2008

Регулярное выражение не предназначалось для проверки диапазонов номеров (это число должно быть от 1 до 5, если число, предшествующее ему, равно 2, а число, предшествующее ему, оказывается ниже 6). Просто посмотрите на схему размещения чисел в регулярных выражениях. Если вам нужно проверить качество даты, поместите ее в объект даты js / c # / vb и соедините числа там.

0 голосов
/ 21 октября 2008

Немного другой подход, который может или не может быть полезным для вас.

Я в php.

Проект, к которому это относится, никогда не будет иметь даты до 1 января 2008 года. Поэтому я беру «date» и использую strtotime (). Если ответ> = 1199167200, тогда у меня есть дата, которая мне пригодится. Если введено что-то, что не похоже на дату, возвращается -1. Если введено значение NULL, оно возвращает номер сегодняшней даты, поэтому сначала вам нужно проверить ненулевую запись.

Подходит для моей ситуации, а может и для вашей?

0 голосов
/ 09 сентября 2008

Если вы собираетесь настаивать на этом с помощью регулярного выражения, я бы порекомендовал что-то вроде:

( (0?1|0?3| <...> |10|11|12) / (0?1| <...> |30|31) |
  0?2 / (0?1| <...> |28|29) ) 
/ (19|20)[0-9]{2}

Это может сделать возможным чтение и понимание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...