Страницы

Поиск по вопросам

четверг, 9 января 2020 г.

Форматирование дат и чисел в тексте

#java #регулярные_выражения


Суть задачи: Есть текст в котором есть даты разного формата 12/9/2010, 15.09.10,
16-09-10, также есть суммы формата 2  300  530 belarusian roubles, 2  351 dollars,
232     500 blr.
Нужно все даты привести к виду September 12, 2010, а из сумм, где есть belarusian
roubles или blr убрать пробелы, суммы dollars оставить как есть. И вывести весь текст
с форматированными датами и суммами.
Для разбора текста использовать регулярные выражения.
Вот что есть:  

public void convertingText (String fileName){
    try (BufferedReader reader = new BufferedReader(
            new InputStreamReader(
                    new FileInputStream(fileName), StandardCharsets.UTF_8))){
        String line;
        Pattern p = Pattern.compile("\\d?\\d[-/.]\\d?\\d[-/.]\\d\\d\\d?\\d?");
        Pattern p1 = Pattern.compile("(\\d[\\d ]*\\d|\\d+) *(bel|blr)");

        while ((line = reader.readLine()) != null) {
            Matcher m = p.matcher(line);
            Matcher m1 = p1.matcher(line);
            if (m.find()) { 
                //Тут должно быть форматирование даты                   
            } 
            if (m1.find()) {
                //Тут форматирование суммы
            }
            System.out.println(line);
        }
    } catch (FileNotFoundException e) {
        System.out.println("File not found.");
    } catch (IOException e){
        e.printStackTrace();
    }   
}


– correct dates in the format: dayXmonthXyear, where the day – one or two digits,
month – one or two digits, year – two or four digits, X – the delimiter character (point,
forward slash or hyphen);  

Initial file in.txt
I was 2  300  530 belarusian roubles and
2  351 dollars 12/9/2010.
After shopping 15.09.10
I was left with 1 700 250 blr and 2 000$.
After shopping 16.09.10
I was left with 1 7  00    2 500 blr.
232     500 blr and 10     blr.  

Result file in.txt
I was 2300530 belarusian roubles and
2  351 dollars September 12, 2010.
After shopping September 15, 2010
I was left with 1700250 blr and 2 000$.
After shopping September 16, 2010
I was left with 17002500 blr.
232500 blr and 10 blr.
Не могу разобраться как сразу все даты привести к одному виду и как убрать пробелы.
    


Ответы

Ответ 1



Исхожу из того, что проблем в поиске дат и валют в тексте у вас не возникло, это следует из вопроса. Для того , чтобы даты привести к одному виду лично я бы сделал так: Найденную в тексте дату передаем в такое выражение в переменной stringDate. LocalDate parse = LocalDate.parse(stringDate, DateTimeFormatter.ofPattern("dd/M/yyyy")); После этого в переменной parse получаем дату, которую с помощью тех же паттернов легко преобразовываем в нужный нам вид с помощью такого кода String result = parse.format(DateTimeFormatter.ofPattern("MMMM dd, yyyy", Locale.ENGLISH)); Теперь в переменной result получаем дату в нужном формате. Соответственно, вы напишите разные регулярные выражения для разных форматов дат. При парсе даты будете также использовать разные паттерны "dd.MM.yy", "dd-MM-yy" и т.д. Я думаю, что идея Вам понятна. Что касается дат, последнее замечание... Паттерн "dd/M/yyyy" не сработает с датой 12/11/2013, потому как месяц указан здесь двумя цифрами, а не одной. Решение проблемы - написание разных регулярных выражений. Альтернатива - оценивать длину переменной типа стринг, передаваемой в паттерн, исходя из чего использовать два разных паттерна - "dd/M/yyyy" и "dd/MM/yyyy". Что касается замены пробелов, то тут все проще. Находите нужное значение, вызываете у стринговой переменной, в которой записано найденное занчение, метод replace (" ", ""); и получаете запись без пробела. Вот альтернатива. После выявления даты с помощью регулярки вызываете нижеописаный метод. private String parseDate (String textDate){ String[] split = textDate.split("\\.|\\-|\\/"); Integer year = Integer.valueOf(split[2].trim()); if (year > 20 && year<1900) year = 1900 + year; else if (year < 20) year = 2000 + year; LocalDate parse =LocalDate.of(year, Integer.valueOf(split[1].trim()), Integer.valueOf(split[0].trim())); return parse.format(DateTimeFormatter.ofPattern("MMMM dd, yyyy", Locale.ENGLISH)); } Если хотите анализировать строку на наличие пробелов и т.д., то, скорее всего, проще пройтись по массиву чаров. Не очень лаконично, но есть полный контроль над результатом. Примерно так private String convertText (String data){ StringBuilder sb = new StringBuilder(); boolean firstLatter = true; for (char ch : data.toCharArray()) { if (Character.isDigit(ch)) sb.append(ch); if (Character.isLetter(ch)) { if (firstLatter) { sb.append(" ").append(ch); firstLatter = false; } else sb.append(ch); } } return sb.toString(); }

Комментариев нет:

Отправить комментарий