DateTimerFormatter в Java - PullRequest
       1

DateTimerFormatter в Java

0 голосов
/ 03 мая 2020

Я получаю ввод от пользователя в этом формате «Вт, 12 мая», и я хотел бы изменить формат на этот: «Tue_12_May».

Формат ввода может иметь 3/4 буквы в месяц Например: May или July или Feb et c. Формат вывода для месяца не имеет значения.

До сих пор я пробовал следующий фрагмент кода:

public static String dateFormatter(String dateWithSpace) {
    DateTimeFormatter formatter1 = new DateTimeFormatterBuilder().parseCaseInsensitive().appendPattern("EEE, dd LLL").toFormatter(Locale.ENGLISH);
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("E_d_M/L");
    LocalDate date = LocalDate.parse(dateWithSpace.trim(), formatter1);
    return date.format(formatter2);
}

Я получаю эту ошибку:

java .time.format.DateTimeParseException: текст «вторник, 12 мая» не может быть проанализирован с индексом 8

Ответы [ 2 ]

3 голосов
/ 03 мая 2020

Хак

    String dateWithSpace = "Tue, 12 May";
    DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .appendPattern("EEE, d [MMMM][MMM]")
            .toFormatter(Locale.ENGLISH);
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("E_d_MMMM", Locale.ENGLISH);
    TemporalAccessor parsed = formatter1.parse(dateWithSpace .trim());
    String formatted = formatter2.format(parsed);

    System.out.println(formatted);

Вывод:

Вт_12_Мая

Проблема в том, что мы не можем представлять «вторник 12 мая» в LocalDate. Для LocalDate нам нужен год. Мы не можем просто принять решение о каком-то фиксированном году по двум причинам: (1) все, что мы решим, вероятно, будет неправильным и, следовательно, приведет к ошибке в нашей программе, даже если ошибка изначально не возникнет; (2) LocalDate будет возражать против неверного дня недели, если нам не удастся выбрать год, когда 12 мая выпадает на вторник. И даже если бы мы каким-то образом принудили это, он не напечатал бы Tue назад, а верный день недели для года, который мы выбрали. Нет другого типа, который бы держал день недели, день месяца и месяц без года.

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

Тем временем мой хак не должен выбирать какой-то конкретный тип, а просто использует неопределенный интерфейс TemporalAccessor.

РЕДАКТИРОВАТЬ: Принимать короткие названия месяцев полностью (June, July, а также May) и трехбуквенные сокращения для более длинных названий месяцев (например, Feb, Dec) Я использую [MMMM][MMM]: необязательное полное имя месяца, за которым следует необязательное сокращение месяца. Поэтому один из них всегда будет совпадать, а другой игнорироваться.

Другие примеры ввода и вывода:

Wed, 1 July  -> Wed_1_July
Thu, 27 Aug  -> Thu_27_August
Mon, 8 Feb   -> Mon_8_February

К вашему коду

У меня есть несколько комментариев, большинство из них второстепенные:

  • Вам не нужно parseCaseInsensitive() для вашего примера строки (возможно, для других строк, которые вы можете получить, я не могу знать).
  • РЕДАКТИРОВАТЬ : Чтобы принять один ди git день месяца, поместите всего одну d в строку шаблона формата для разбора. Он по-прежнему будет принимать две цифры тоже. Далее решите, хотите ли вы, чтобы в выходных данных всегда были две цифры или только одна ди git для первых 9 дней месяца.
  • Предпочитайте MMM над LLL в шаблоне формата для анализа. LLL для случая, когда месяц не является частью даты (в некоторых языках разница в том, какую форму имени месяца использовать).
  • Для форматирования тоже используйте MMM для сокращения месяца , не M/L.
  • Укажите языковой стандарт для форматирования.
0 голосов
/ 03 мая 2020

Вы можете сделать это просто так:

public static String dateFormatter(String dateWithSpace) {
    DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
                    .appendOptional(DateTimeFormatter.ofPattern("E, d LLLL"))
                    .appendOptional(DateTimeFormatter.ofPattern("E, d LLL"))
                    .toFormatter();
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("E_d_LLL");
    return formatter2.format(formatter1.parse(dateWithSpace));
}

В вашем случае проблема в том, что вы используете LocalDate, но пропускаете один важный параметр LocalDate, то есть год. Вы можете обратиться к LocalDate Документации :

LocalDate - это неизменяемый объект даты-времени, который представляет дату, часто рассматриваемую как год-месяц-день. Другие поля даты, такие как день года, день недели и неделя года, также могут быть доступны. Например, значение «2 октября 2007» может быть сохранено в LocalDate.

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