Java 8 DateTimeFormatter 解析具有不同重要性的可选小数秒

2022-09-01 17:08:14

我的 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) };
    }
}

我正在尝试使用DateTimeFormatter测试具有不同重要性的可选小数秒的日期时间解析。Javadoc的相关部分如下:String

分数:将秒的纳级字段输出为秒的小数部分。纳秒值有九位数字,因此图案字母的计数从1到9。如果它小于 9,则秒的纳秒值将被截断,仅输出最高有效位数。

基于我有限的理解,我曾经将小数秒标记为可选,并且由于我对不同的重要性感兴趣,我认为我应该坚持.[...]SSSSSSSSS

但是,单元测试在解析毫秒和微秒时失败,即第二种和第三种情况。将 更改为 LENIENT 在这里没有帮助,因为它在解析阶段失败,而不是在分辨率上失败。ResolverStyle

我可以知道我应该考虑哪些方法来解决我的问题吗?我应该使用DateTimeFormatterBuilder来选择性地指定每个小数位数(9次),还是我的模式有一种“更智能”的方式?

编辑我最终找到了自己的答案...仍然会将此作为一天的未回答,看看是否有其他方法。


答案 1

哦,很酷,又过了15分钟的故障排除,得出了这个结果:

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

编辑可选的parseLenient()


答案 2

推荐