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

171
08 февраля 2018, 16:48

Суть задачи: Есть текст в котором есть даты разного формата 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.
Не могу разобраться как сразу все даты привести к одному виду и как убрать пробелы.

Answer 1

Исхожу из того, что проблем в поиске дат и валют в тексте у вас не возникло, это следует из вопроса.

Для того , чтобы даты привести к одному виду лично я бы сделал так:

  1. Найденную в тексте дату передаем в такое выражение в переменной stringDate.

    LocalDate parse = LocalDate.parse(stringDate, DateTimeFormatter.ofPattern("dd/M/yyyy"));

  2. После этого в переменной 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();
}
READ ALSO
слушатель буфера обмена

слушатель буфера обмена

Возможно ли написать программу без UI , которая будет слушать изменения в буфере обмена? Например: запустил программу, далее захожу например...

209
Правильный тип для String int double boolean

Правильный тип для String int double boolean

Задача стоит в проектировании БД для интернет магазина

169
Удаление символа из строки

Удаление символа из строки

Здравствуйте, вот такая проблемаКак из строки удалить символы [], если ] ещё можно удалить, то с [ я не справился

238
В чем ошибка scanner.nextInt();?

В чем ошибка scanner.nextInt();?

Добрый деньРебята, подскажите что здесь не так? Вот ошибка

171