Найти несколько форматов даты в строке JSON - PullRequest
0 голосов
/ 25 февраля 2019

В настоящее время я работаю на Java, и у меня есть проблема, связанная с несколькими форматами даты в строке JSON с использованием регулярных выражений.

JSON:

{"x": "02/23/2019", "y": "02-27-2019"}

регулярных выражений:

[0-9]{1,2}(/|-)[0-9]{1,2}(/|-)[0-9]{4}

В тестере Regex это регулярное выражение соответствует обеим датам.Но в коде Java я получаю только одну дату из группы.Вторая группа это просто "\".

Код Java:

private static void findDates() {
    String regex = "[0-9]{1,2}(/|-)[0-9]{1,2}(/|-)[0-9]{4}";
    Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
    String json =
            "{\"x\":\"02/23/2019\",\n" +
             "\"y\":\"02-27-2019\"}";
    Matcher matcher = pattern.matcher(json);
    if (matcher.find()) {
        for (int i = 0; i < matcher.groupCount(); i++) {
            String dateMatch = matcher.group(i);
            System.out.println(dateMatch);
        }
        System.out.println(json);
    }
}

Мне нужно иметь возможность захватывать все вхождения дат, которые соответствуют формату, указанному в регулярном выражении.Таким образом, если в JSON есть три даты в форматах MM / dd / yyyy или MM-dd-yyyy, при выполнении итерации по группам я должен получить все три даты, или все пять дат, или все две даты и т. Д...

Ответы [ 2 ]

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

Regex - это слишком много

Если у вас в игре ограниченное количество не двусмысленных форматов, просто попробуйте выполнить синтаксический анализ с классами LocalDate & DateTimeFormatter.Это то, для чего они были созданы.

Определение шаблонов форматирования для соответствия ожидаемым входным данным.

List < String > inputs = List.of( "02/23/2019" , "02-27-2019" , "07|07|2022" );
List < DateTimeFormatter > formatters =
        List.of(
                DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ,
                DateTimeFormatter.ofPattern( "MM-dd-uuuu" )
        );

Соберите результаты вместе с неверными (неожиданными) входными данными.

List < LocalDate > results = new ArrayList <>( inputs.size() );
List < String > faultyInputs = new ArrayList <>();

Цикл входов.Для каждой строки выполните цикл определенных вами форматеров.Если один форматтер успешно (соответствует формату вашего ввода и успешно анализирует), собрать результат.В противном случае, если ни один из форматеров не соответствует входному значению, соберите ошибочный ввод.

for ( String input : inputs )
{
    LocalDate ld = null;
    for ( DateTimeFormatter formatter : formatters )
    {
        try
        {
            ld = LocalDate.parse( input , formatter );
            results.add( ld );
            break; // Bail-out of looping the formatters. If a format matched, no need to try others.
        } catch ( DateTimeParseException e )
        {
            // Swallow exception. No code needed here.
        }
    }
    if ( Objects.isNull( ld ) ) // If we tried all the expected formats but not matched our input…
    {
        faultyInputs.add( input );
    }
}

Дамп на консоль.

System.out.println( "results:" );
System.out.println( results );
System.out.println( "faultyInputs:" );
System.out.println( faultyInputs );

результаты:

[2019-02-23, 2019-02-27]

неисправные Входы:

[07 | 07 | 2022]

ISO 8601

Совет: Обучите любого, кто производит такие данные, радостям ISO 8601 .Обмен значениями даты и времени в текстовом формате с использованием локализованных или изобретенных форматов - плохая практика.


О java.time

java.timeФреймворк встроен в Java 8 и более поздние версии.Эти классы вытесняют старые классные устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java.time классы.

Вы можете обмениваться java.time объектами напрямую с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

  • Java SE 8 , Java SE 9 , Java SE 10, Java SE 11 и более поздние версии - часть стандартного Java API с связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и JavaSE 7
    • Большинство функций java.time перенесены в Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии пакетов Android для реализации java.time классы.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

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

Ваш код немного неверный.Когда вы пытаетесь найти все совпадения, вам нужно использовать while(matcher.find()).Также вы можете написать (/|-) как [/-].Проверьте этот Java-код.

String regex = "[0-9]{1,2}([/-])[0-9]{1,2}\\1[0-9]{4}";
Pattern pattern = Pattern.compile(regex);
String json = "{\"x\":\"02/23/2019\",\n" + "\"y\":\"02-27-2019\"}";

Matcher matcher = pattern.matcher(json);
while (matcher.find()) {
    System.out.println(matcher.group());
}

Печатает обе даты,

02/23/2019
02-27-2019

Обратите внимание, я написал \\1 вместо ([/-]) перед частью года в регулярном выражении,так что он не соответствует датам формата, 02-23/2019 или 02/23-2019 и вместо этого только 02-23-2019 и 02/23/2019

Кроме того, если в вашем коде вы используете if (matcher.find()), тогда matcher будет простосначала найдите и не найдете дальнейших совпадений в вашей строке, даже если многие из них действительно существуют.И matcher.groupCount() просто дает вам количество групп в вашем подходящем регулярном выражении, которое вы используете для печати всех групповых снимков, что не является вашим намерением в вашей программе.

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