2015-05-07 2 views
12

Мои MCVE (в качестве испытания TestNG единицы):Java 8 DateTimeFormatter разборе необязательных дробных секунд различной значимости

public class MyDateTimeFormatterTest { 

    private static final String BASE_PATTERN = "yyyy/MM/dd HH:mm:ss"; 
    private static final DateTimeFormatter FORMATTER = 
      DateTimeFormatter.ofPattern(BASE_PATTERN + "[.SSSSSSSSS]"); 
    private static final LocalDateTime TEST_INPUT = 
      LocalDateTime.of(2015, 5, 4, 12, 34, 56, 123456789); 

    @DataProvider(name = "test-cases") 
    public Iterator<Object[]> getTestCases() { 
     return Arrays.asList(testFor("", ChronoUnit.SECONDS), 
       testFor(".SSS", ChronoUnit.MILLIS), 
       testFor(".SSSSSS", ChronoUnit.MICROS), 
       testFor(".SSSSSSSSS", ChronoUnit.NANOS)).iterator(); 
    } 

    @Test(dataProvider = "test-cases") 
    public void testWithDefaultResolution(String input, LocalDateTime output) { 
     assertThat(FORMATTER.parse(input, LocalDateTime::from), equalTo(output)); 
    } 

    private Object[] testFor(String patternSuffix, TemporalUnit truncatedTo) { 
     return new Object[] { DateTimeFormatter.ofPattern(BASE_PATTERN + patternSuffix) 
       .format(TEST_INPUT), TEST_INPUT.truncatedTo(truncatedTo) }; 
    } 
} 

Я пытаюсь проверить парсинг дата-время String с факультативных дробных секунд различное значение с использованием DateTimeFormatter. Соответствующая часть Javadoc гласит:

Фракция: Выходы на поле нано-в-секунду в виде дроби-в-секунду. Значение nano-of-second имеет девять цифр, поэтому количество букв шаблона составляет от 1 до 9. Если оно меньше 9, то значение nano-of-second усекается, и выводятся только самые значащие цифры.

Исходя из моего ограниченного понимания, я использовал [...] для обозначения доли секунд, как опция, и так как я заинтересован в том или ином смысл, я думал, что я должен придерживаться SSSSSSSSS.

Однако при тестировании устройства не выполняется разбор до миллисекунд и микросекунд, то есть второй и третий случаи. Изменение ResolverStyle на LENIENT здесь не помогает, поскольку оно не срабатывает на этапе синтаксического анализа, а не в разрешении.

Могу ли я узнать, какие подходы следует рассмотреть, чтобы решить мою проблему? Должен ли я использовать DateTimeFormatterBuilder для опционального указания каждой дробной цифры (9 раз), или есть более «умный» способ с моим шаблоном?

Редактировать Я нашел свой собственный ответ в конце ... все равно оставит это без ответа в течение дня и посмотрит, есть ли другие подходы или нет.

+1

Вы также видите этот вопрос: http://stackoverflow.com/questions/30103167/jsr-310-parsing-seconds-fraction-with-variable-length? Похоже, ваш ответ по существу тот же – araqnid

+0

@araqnid благодарит за то, что указав это ... Я обновил свой собственный ответ ниже, чтобы отбросить 'parseLenient()' тоже, для будущих ссылок ... –

ответ

18

О, круто, еще 15 минут поиска неисправностей дали это:

private static final DateTimeFormatter FORMATTER = 
    new DateTimeFormatterBuilder().appendPattern(BASE_PATTERN) // .parseLenient() 
     .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true).toFormatter(); 

редактироватьparseLenient() является optional.