Регулярное выражение для соответствия действительному дню в дате - PullRequest
10 голосов
/ 20 мая 2011

Мне нужна помощь, чтобы придумать регулярное выражение, чтобы убедиться, что пользователь вводит правильную дату Строка будет в формате mm/dd/yyyy

Вот то, что я придумал до сих пор.

/\[1-9]|0[1-9]|1[0-2]\/\d{1,2}\/19|20\d\d/

Я проверил регулярное выражение, в котором пользователь не может ввести день, превышающий 12, а годы должны начинаться с "19" или "20". У меня проблемы с определением логики для подтверждения дня. День не должен проходить больше 31.

Ответы [ 8 ]

35 голосов
/ 21 мая 2011

регулярное выражение для 0-31:

(0[1-9]|[12]\d|3[01])

Или, если вам не нужны дни с предшествующим нулем (например, 05):

([1-9]|[12]\d|3[01])
12 голосов
/ 21 мая 2011
use DateTime;

Другие решения хороши, возможно, работают и т. Д. Как правило, вы в конечном итоге хотите сделать немного больше, а затем немного больше, и в конечном итоге у вас есть какой-то сумасшедший код, и високосные годы, и почему высделать это снова самостоятельно?

DateTime и его форматеры - это ваше решение.Используй их!Иногда они немного излишни, но часто это помогает вам в будущем.

my $dayFormat = new DateTime::Format::Strptime(pattern => '%d/%m/%Y');
my $foo = $dayFormat->parse_datetime($myDateString);

$foo теперь объект DateTime.Наслаждаться.

Если строка даты не была правильно отформатирована, $foo будет "undef" и $dayFormat->errstr скажет вам, почему.

8 голосов
/ 09 декабря 2013
  • Как уже отмечали многие, если мы хотим проверить дату в целом, то RegEx - очень плохой выбор.
  • Но если мы хотим соответствовать шаблону чисел , в данном случае от 01-31, то с RegEx все в порядке, если есть некоторая логика бэкэнда, которая проверяет дату в целом, если это желательно .
  • Я вижу ожидаемый ответ в настоящее время не для 10, 20.

    • Тест: gawk 'BEGIN{ for(i=0;i<=32;i++){ if (i ~ /^([0-2]?[1-9]|3[01])$/){print i " yes"}else {print i " no"} } }
    • Это можно исправить следующим образом: ^([0-2]?[1-9]|3[01]|10|20)$

Пожалуйста, рассмотрите приведенное ниже решение ...

1. Определите наборы, которые должны быть сопоставлены:

  • Дни с префиксом "0": {01,...,09},{10,...,31}
    • Подмножество {10,...,31} можно разбить на => {10,...,29},{30,31}
  • Без префикса: {1,...,31} => {1,...,9},{10,...,31}

2. Соответствующие регулярные выражения для каждого подмножества:

---------------------------------
Sub-Set     |  Regular-Expression
---------------------------------
{01,...,09} | [0][1-9]
{10,...,29} | [1-2][0-9]
{30,31}     | 3[01]
{1,...,9}   | [1-9]
---------------------------------

Теперь мы можем сгруппировать ([0][1-9]) и ([1-9]) вместе как ([0]?[1-9]). Где ? обозначает 0 или 1 вхождение шаблона / символа. [ОБНОВЛЕНИЕ] - Спасибо @MattFrear за указание на это.

Таким образом, в результате RegEx: ^(([0]?[1-9])|([1-2][0-9])|(3[01]))$

Проверено здесь: http://regexr.com/?383k1 [ОБНОВЛЕНИЕ]

5 голосов
/ 21 мая 2011
^(((((((0?[13578])|(1[02]))[\.\-/]?((0?[1-9])|([12]\d)|(3[01])))|(((0?[469])|(11))[\.\-/]?((0?[1-9])|([12]\d)|(30)))|((0?2)[\.\-/]?((0?[1-9])|(1\d)|(2[0-8]))))[\.\-/]?(((19)|(20))?([\d][\d]))))|((0?2)[\.\-/]?(29)[\.\-/]?(((19)|(20))?(([02468][048])|([13579][26])))))$

От Выражения в категории: Даты и время

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

Конечно, вы можете изменить [\.\-/] на /, чтобы разрешить только косые черты.

2 голосов
/ 21 мая 2011

Это не все , что трудно ...

qr#^
    (?: 0[1-9] | 1[012] )
    /
    (?:
        0[1-9] | 1[0-9] | 2[0-8]
        | (?<! 0[2469]/ | 11/ ) 31
        | (?<! 02/ ) 30
        | (?<! 02/
             (?= ... 
                 (?: 
                     .. (?: [02468][1235679] | [13579][01345789] )
                     | (?: [02468][1235679] | [13579][01345789] ) 00
                 )
             )
        ) 29
    )
    /
    [0-9]{4}
    \z
#x
1 голос
/ 21 мая 2011

Регулярное выражение обязательно? Если нет, то лучше использовать другой подход, например DateTime::Format::DateManip

my @dates = (
    '04/23/2009',
    '01/22/2010 6pm',
    'adasdas',
    '1010101/12312312/1232132'
);

for my $date ( @dates ) 
{
    my $date = DateTime::Format::DateManip->parse_datetime( $date );
    die "Bad Date $date"  unless (defined $date);
    print "$dt\n";
}
1 голос
/ 21 мая 2011

Попробуйте:
/(0?[1-9]|1[012])\/(0?[1-9]|[12][0-9]|3[01])\/((19|20)\d\d)/

0 голосов
/ 21 февраля 2019

Регулярное выражение для 0-31 дня:

0 [1-9] | [12] \ d | 3 [01]) без префикса 0 - когда «1», «23» ...

([1-9] | [12] \ d | 3 [01]) с префиксом 0 - когда «01», «04»

(0? [1-9] |[12] \ d | 3 [01]) - с или без "0" - когда ""

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