Создайте пользовательский формат даты с помощью DateTimeFormatterBuilder и игнорируйте необработанный текст между полями Chrono - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь создать надежное решение для поддержки различных форматов даты, используя DateTimeFormatterBuilder. Я хочу иметь возможность анализировать практически любую строку даты, которую предоставляет пользователь, зная только порядок дня / месяца / года / часов / минут / секунд.

Я подумал о двух решениях:

  1. с использованием регулярного выражения для замены всех известных разделителей конкретным разделителем (например, "?") И использованием DateTimeFormatterBuilder для создания пользовательского формата даты.

  2. в основном то же самое, но вместо этого я предоставлю список «известных» разделителей и добавлю их как необязательные для theDateTimeFormatterBuilder

Примечание. Одна из проблем, с которыми мы сталкиваемся, заключается в несовместимости пробелов между компонентами даты и времени (например: dd_MM YYYY или dd _____ MM__YYYY)

Примечание 2- Производительность имеет решающее значение

Мой вопрос: есть ли способ избежать всего этого и использовать некоторые встроенные метод игнорирования текста между годом, месяцем, днем ​​и т. д. (что-то вроде необязательного)

решения 1 (для простоты, например, порядок день-месяц-год):

private static final String[] DELIMITTER= {"?"};
public static void main(String[] args) {
    DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder().appendValue(ChronoField.DAY_OF_MONTH);
    appendDelims(builder);
    builder.appendValueReduced(ChronoField.MONTH_OF_YEAR,1,2,1);
    appendDelims(builder);
    builder.appendValueReduced(ChronoField.YEAR, 2, 4, LocalDate.ofEpochDay(0));
    DateTimeFormatter dateTimeFormatter = builder.toFormatter();
    System.out.println("dt = " + LocalDate.parse("23     2,,,,05".replaceAll("\\s+|-+|,+","?"),dateTimeFormatter));
    System.out.println("dt2 = " + LocalDate.parse("09-----2      2015".replaceAll("\\s+|-+|,+","?"), dateTimeFormatter));
}

private static void appendDelims(DateTimeFormatterBuilder dtb){
    for(String d : DELIMITTER) {
        dtb.appendOptional(DateTimeFormatter.ofPattern(d));
    }
}

Выход - DT = 2005-02-23 dt2 = 2015-02-09

решение 2 -

private static final String[] DELIMITTER= {"?","-"," ","  "};
public static void main(String[] args) {
    DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder().appendValue(ChronoField.DAY_OF_MONTH);
    appendDelims(builder);
    builder.appendValueReduced(ChronoField.MONTH_OF_YEAR,1,2,1);
    appendDelims(builder);
    builder.appendValueReduced(ChronoField.YEAR, 2, 4, LocalDate.ofEpochDay(0));
    DateTimeFormatter dateTimeFormatter = builder.toFormatter();
    System.out.println("dt = " + LocalDate.parse("23?2 05",dateTimeFormatter));
    System.out.println("dt2 = " + LocalDate.parse("9?2-2015", dateTimeFormatter));
}

private static void appendDelims(DateTimeFormatterBuilder dtb){
    for(String d : DELIMITTER) {
        dtb.appendOptional(DateTimeFormatter.ofPattern(d));
    }
}

Выход - DT = 2005-02-23 dt2 = 2015-02-09

1 Ответ

0 голосов
/ 19 ноября 2018

Нет, разумного способа избежать как вашего решения 1, так и вашего решения 2. В DateTimeFormatter и DateTimeFormatterBuilder имеются только механизмы, позволяющие игнорировать различные разделители, - те, которые делают части формата необязательными:

  1. appendOptional, которые вы уже используете
  2. optionalStart и optionalEnd
  3. квадратные скобки [ и ] в шаблоне формата.

Конечно, есть и другие возможности, такие как написание собственного парсера с нуля, но я бы не советовал по поводу того, что вы уже делаете.

В вашем решении 1, поскольку вызаменяя разделители, я думаю, вам не нужны звонки на appendDelims.Следующий форматтер работает для меня в двух ваших примерах:

        DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder().appendValue(ChronoField.DAY_OF_MONTH)
                .appendPattern("?M?")
                .appendValueReduced(ChronoField.YEAR, 2, 4, LocalDate.EPOCH)
                .toFormatter();

PS Не используйте appendValueReduced в течение месяца, это просто сбивает с толку.Используйте одну букву шаблона M для соответствия номеру месяца из 1 или 2 цифр, например, 8, 08 или 11.

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