Анализ Java 8 DateTimeFormatter для необязательных дробных секунд различного значения

Мой MCVE (как TestNG модульный тест):

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 гласит:

Дробь: выводит поле наносекунд как долю секунды. Значение наносекунды состоит из девяти цифр, поэтому количество букв шаблона составляет от 1 до 9. Если оно меньше 9, то значение наносекунды усекается, и выводятся только самые значащие цифры.

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

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

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

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


person h.j.k.    schedule 07.05.2015    source источник
comment
Вы также видели этот вопрос: stackoverflow.com/questions/30103167/ ? Похоже, ваш ответ по существу тот же   -  person araqnid    schedule 08.05.2015
comment
@araqnid спасибо, что указали на это ... Я обновил свой собственный ответ ниже, чтобы также удалить parseLenient() для будущих ссылок ...   -  person h.j.k.    schedule 08.05.2015


Ответы (1)


О, круто, еще 15 минут устранения неполадок дали следующее:

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

редактировать parseLenient() необязательно.

person h.j.k.    schedule 07.05.2015