解析年份时java.time.format.DateTimeParseException

时间:2020-02-03 12:08:31

标签: java java-8

使用的jdk:1.8

不确定是什么问题,configureFormat是有效的,inputTime也有效,真的很困惑是什么问题。

public class Test {

    public static void main(String[] args) {
        String configuredFormat = "yyyyMMddHHmmssSSS";
        String inputTime = "20200203164553123";

        DateTimeFormatter dt = DateTimeFormatter.ofPattern(configuredFormat);
        DateTimeFormatter strictTimeFormatter = dt.withResolverStyle(ResolverStyle.STRICT);
        try {
            LocalTime.parse(inputTime, strictTimeFormatter);
            System.out.println("success");
        } catch (DateTimeParseException | NullPointerException e) {
            e.printStackTrace();
        }
    }
}

我得到的异常:

java.time.format.DateTimeParseException: Text '20200203164553123' could not be parsed at index 0
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.LocalTime.parse(LocalTime.java:441)
    at com.Test.main(Test.java:20)

2 个答案:

答案 0 :(得分:10)

很幸运,有一个确切错误报告,该报告使用与您尝试的模式完全相同的模式。谁比JDK维护者更好解释?

JDK-8031085

解决方法

DateTimeFormatter dtf = new
DateTimeFormatterBuilder()
    .appendPattern("yyyyMMddHHmmss")
    .appendValue(ChronoField.MILLI_OF_SECOND,3)
    .toFormatter()

相邻值解析通常是一个难题。目的是 处理第一个元素为可变宽度(年份)的情况 而所有其他元素都是固定宽度(月,日等)。然而 “ S”模式字母是分数,而不是值。具体来说, 小数可以是可变宽度-大于或小于三位数 可能的选择。考虑到可变宽度年份的一般情况, 可变宽度毫秒,无法确定 这两个字段是可变的。

话虽如此,实现(和javadoc)尚未结束 如我所愿DateTimeFormatter中“分数”的描述 以严格和宽容的模式描述操作,但是没有办法 使用时进入严格或宽松模式 DateTimeFormatter.ofPattern()。这是一个文档错误,应该 通过删除对严格与宽大的讨论来解决。

但是,更糟糕的是,SSS模式因此最终使用了 宽容模式时适合的严格模式。由于目前 看台,DateTimeFormatter.ofPattern(“ hhmmss.SSS”)需要三个 最初要求为0的毫秒数 到9(宽容的行为)。

我尝试更改整个DateTimeFormatter.ofPattern()方法 使用宽大的解析,并且没有失败的测试(这本身就是不好的 道路)。这可能是一个有效的修复程序,但仅当包含在JDK 8中时, 一旦人们适应了严格的解析,就很难做到 宽大。

鉴于当前的实现方式,SSS需要三位数字, 因此非常令人惊讶的是,不应用相邻值解析。

答案 1 :(得分:4)

实际上,我同意格式应该是有效的……这似乎已得到确认,因为我在oracle java 8和9运行时中都尝试过,而在java 9中却没有发生。 (我也尝试过IBM jre 8,它也可以正常工作)

        System.out.println( System.getProperty( "java.vendor" )+" - "+System.getProperty( "java.version" ) );
        String configuredFormat = "yyyyMMddHHmmssSSS";
        String inputTime = "20200203164553123";
        DateTimeFormatter dt = DateTimeFormatter.ofPattern(configuredFormat);
        DateTimeFormatter strictTimeFormatter = dt.withResolverStyle(ResolverStyle.STRICT);
        try {
            //System.out.println( dt.parse( inputTime ) );
            LocalTime.parse(inputTime, strictTimeFormatter);
            System.out.println("success");
        } catch (DateTimeParseException | NullPointerException e) {
            e.printStackTrace();
        }

输出

Oracle Corporation - 9.0.4
success


IBM Corporation - 1.8.0_211
success

Oracle Corporation - 1.8.0_172
java.time.format.DateTimeParseException: Text '20200203164553123' could not be parsed at index 0
    at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
    at java.time.format.DateTimeFormatter.parse(Unknown Source)
    at java.time.LocalTime.parse(Unknown Source)
    at test.Test2.main(Test2.java:19)