2015-09-30 3 views
4

Я хочу проанализировать текст в дату. Однако нет гарантии, что текст имеет желаемый формат. Это может быть 2012-12-12 или 2012 или даже .Элегантное решение для синтаксического анализа даты

В настоящее время я иду по пути к вложенным блокам try-catch, но это нехорошее направление (я полагаю).

LocalDate parse; 
try { 
    parse = LocalDate.parse(record, DateTimeFormatter.ofPattern("uuuu/MM/dd")); 
} catch (DateTimeParseException e) { 
    try { 
     Year year = Year.parse(record); 
     parse = LocalDate.from(year.atDay(1)); 
    } catch (DateTimeParseException e2) { 
     try { 
       // and so on 
     } catch (DateTimeParseException e3) {} 
    } 
} 

Какое изящное решение этой проблемы? Можно ли использовать Optional s, отсутствующий в случае исключения во время оценки? Если да, то как?

+1

вы должны использовать для массива, чтобы сохранить все ваши формы. – Satya

+0

В одном из первых компьютеров Mac вы можете даже ввести «завтра», «вторник» и так далее. –

+0

u может использовать библиотеку pojava, если требуется больше функциональности ... например, обработка dd-MM-yyyy – gladiator

ответ

4

DateTimeFormatterBuilder класс содержит строительные блоки, чтобы сделать эту работу:

LocalDate now = LocalDate.now(); 
DateTimeFormatter fmt = new DateTimeFormatterBuilder() 
    .appendPattern("[uuuu[-MM[-dd]]]") 
    .parseDefaulting(ChronoField.YEAR, now.getYear()) 
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, now.getMonthValue()) 
    .parseDefaulting(ChronoField.DAY_OF_MONTH, now.getDayOfMonth()) 
    .toFormatter(); 
System.out.println(LocalDate.parse("2015-06-30", fmt)); 
System.out.println(LocalDate.parse("2015-06", fmt)); 
System.out.println(LocalDate.parse("2015", fmt)); 
System.out.println(LocalDate.parse("", fmt)); 

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

Обратите внимание на использование разделов «[...]» в шаблоне, чтобы определить, что является необязательным.

+0

Как-то можно сделать 'System.out.println (LocalDate.parse (« 2015-06-00 », fmt)); ? Так что в этот день '00' по умолчанию используется' now.getDayOfMonth() '? – helt

+0

Если вы используете стиль слабительного разрежения, вы можете сделать его синтаксическим составлением до 2015-05-31. Но вы не можете достичь того, чего хотите, не ограничивая что-то еще. – JodaStephen

5

Это можно сделать элегантным способом, используя DateTimeFormatter необязательные разделы. Необязательный раздел запускается токеном [ и заканчивается маркером ].

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[yyyy[-MM-dd]]"); 
System.out.println(formatter.parse("2012-12-12")); // prints "{},ISO resolved to 2012-12-12" 
System.out.println(formatter.parse("2012")); // prints "{Year=2012},ISO" 
System.out.println(formatter.parse("")); // prints "{},ISO" 
+0

да, это хорошо. Однако 'formatter.parse (« 2012 »)' будет вызывать исключение, потому что его несовместимо с 'LocalDate', когда не дано ни дня, ни месяца – helt

+0

@helt Нет, это не будет, будет создан объект Year. DateTimeFormatter не всегда создает LocalDate, он создает общий TemporalAccessor. Вы можете проверить мой код, чтобы убедить себя. – Tunaki

+0

Хорошо. Благодарю. И потом, я тщательно создаю свой собственный LocalDate, используя 'TemporalAccessor.isSupported', правильно? Или есть лучшее решение? ;) – helt

Смежные вопросы