Почему эти данные YYYY-MM-DD регулярное выражение терпят неудачу в Java? - PullRequest
10 голосов
/ 24 марта 2010

Мой первый вопрос, и я взволнован ... Я с тех пор скрываюсь, живу и люблю этот сайт, однако я прошу прощения за любые ошибки новичков, форматирование и т. Д. ...

Я пытаюсь проверить формат строкового поля, содержащего дату в Java. Мы получим дату в виде строки, я проверю ее формат, прежде чем разбирать ее на настоящий объект Date. Формат передачи в формате ГГГГ-ММ-ДД. Однако я застрял на одном из моих тестов, если я пройду в «1999-12-33», тест провалится (как это должно быть с днем ​​33) с этим неполным шаблоном:

((19|20)\\d{2})-([1-9]|0[1-9]|1[0-2])-([12][0-9]|3[01])

Однако, как только я добавляю символы, выделенные жирным шрифтом ниже, он проходит тест (но не должен)

((19|20)\\d{2})-([1-9]|0[1-9]|1[0-2])-(<b>0[1-9]|[1-9]|</b>[12][0-9]|3[01])

* дополнительное примечание, я знаю, что могу изменить 0[1-9]|[1-9] на 0?[1-9], но я хотел разбить все до его самого простого формата, чтобы попытаться выяснить, почему это не работает.

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

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class scrapTest {
    public scrapTest() {
    }

    public static void main(String[] args) {

        scrapTest a = new scrapTest();
        boolean flag = a.verfiyDateFormat("1999-12-33");
    }   

    private boolean verfiyDateFormat(String dateStr){
        Pattern datePattern = Pattern.compile("((19|20)\\d{2})-([1-9]|0[1-9]|1[0-2])-(0[1-9]|[1-9]|[12][0-9]|3[01])");
        Matcher dateMatcher = datePattern.matcher(dateStr);
        if(!dateMatcher.find()){
            System.out.println("Invalid date format!!! -> " + dateStr);
            return false;
        }
        System.out.println("Valid date format.");
        return true;
    } 
}

Я программировал в течение ~ 10 лет, но был чрезвычайно новым для Java, поэтому, пожалуйста, не стесняйтесь объяснять что-нибудь настолько элементарное, насколько вы считаете нужным.

Ответы [ 5 ]

8 голосов
/ 24 марта 2010

Я думаю, это потому, что вы используете dateMatcher.find() вместо dateMatcher.matches(). Первый ищет совпадение, последний пытается сопоставить всю строку. См. Страницу API . Таким образом, в основном первые 3 из 33 будут соответствовать [1-9], который вы только что добавили, а вторые 3 не будут сопоставлены ничему, но метод все еще возвращает true.

5 голосов
/ 24 марта 2010

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

второй случай, [1-9], выглядит как часть, которая успешно выполняется, так как у вас нет теста на конец строки.

Это соответствует 1999-12-3, а не 1999-12-33

3 голосов
/ 24 марта 2010

Как насчет использования SimpleDateFormat, созданного только для этого?

Date d = new SimpleDateFormat("yyyy-MM-dd").parse(somestring);
if (d == null) {
    // somestring is not a Date
} else {
    // d is the Date
}

Документы для SimpleDateFormat

2 голосов
/ 24 марта 2010

Не совсем ответ на вопрос, но предложение: напишите более простое регулярное выражение, а затем выполните числовую проверку в Java, а не в своем регулярном выражении:

(\\d{4})-(\\d{2})-(\\d{2})

Сравните это с вашим вводом, извлеките соответствующие группы и преобразуйте в целые числа, затем проверьте части года, месяца и дня, чтобы убедиться, что они находятся в допустимом диапазоне.

1 голос
/ 24 марта 2010

Как сказал Броам, ваш шаблон находит часть даты для соответствия, чтобы соответствовать всей входной строке, используйте:

if (!dateMatcher.matches()) {

вместо find().

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