Ответ 1
Regex для 0-31:
(0[1-9]|[12]\d|3[01])
Или, если вам не нужны дни с предшествующим нулем (например, 05):
([1-9]|[12]\d|3[01])
Мне нужна помощь при появлении регулярного выражения, чтобы убедиться, что пользователь вводит действительную дату
Строка будет в формате mm/dd/yyyy
Вот что я придумал до сих пор.
/\[1-9]|0[1-9]|1[0-2]\/\d{1,2}\/19|20\d\d/
Я проверил регулярное выражение, в котором пользователь не может ввести день, превышающий 12, и годы должны начинаться с "19" или "20". У меня возникают проблемы с выяснением некоторой логики для проверки дня. День не должен превышать 31.
Regex для 0-31:
(0[1-9]|[12]\d|3[01])
Или, если вам не нужны дни с предшествующим нулем (например, 05):
([1-9]|[12]\d|3[01])
use DateTime;
Другие решения прекрасны, возможно, работают и т.д. Обычно вы хотите сделать немного больше, а затем немного больше, и в конце концов у вас есть какой-то сумасшедший код и високосные годы, и почему вы делаете это самостоятельно снова?
DateTime и formatters - это ваше решение, Используй их! Иногда они немного перегружены, но часто это работает для вас по дороге.
my $dayFormat = new DateTime::Format::Strptime(pattern => '%d/%m/%Y');
my $foo = $dayFormat->parse_datetime($myDateString);
$foo
теперь является объектом DateTime. Наслаждаться.
Если ваша строка даты не была правильно отформатирована, $foo
будет "undef"
и $dayFormat->errstr
расскажет вам, почему.
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. Определите наборы, которые должны быть сопоставлены:
{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 [ОБНОВЛЕНИЕ]
^(((((((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])))))$
Из Выражения в категории: Даты и время
Проверяет правильное количество дней в месяце, похоже, что даже обрабатывает високосные годы.
Вы можете, конечно, изменить [\.\-/]
на /
только для разрешений.
Это не так сложно...
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
Попробуйте: /(0?[1-9]|1[012])\/(0?[1-9]|[12][0-9]|3[01])\/((19|20)\d\d)/
Является ли регулярное выражение обязательным? Если нет, вам лучше использовать другой подход, например 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";
}
Регулярное выражение на 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" - когда ""
Упрощенное регулярное выражение:
([12]\d|3[01]|0?[1-9])
Рассмотрите принятый ответ и это выражение:
(0[1-9]|[12]\d|3[01])
Это соответствует 01, но не 1
Другое выражение в принятом ответе:
([1-9]|[12]\d|3[01])
Это соответствует 1, но не 01
Невозможно добавить предложение OR, чтобы заставить их обоих работать.
Тот, который я предложил, соответствует обоим. Надеюсь это поможет.
Я работал с этим некоторое время, и лучшим из предложенных мной регулярных выражений является следующее:
\b(0)?(?(1)[1-9]|(3)?(?(2)[01]|[12][0-9]))\b|\b[1-9]\b
Он будет соответствовать следующим номерам:
1 01 10 15 20 25 30 31
Это не соответствует следующему:
32 40 50 90