java.time.format.DateTimeParseException 在 java 17 中,但在 java 11 中没有

java.time.format.DateTimeParseException in java 17 but not in java 11

提问人:Anurator 提问时间:7/12/2023 最后编辑:Arvind Kumar AvinashAnurator 更新时间:7/21/2023 访问量:430

问:

我正在将服务从 jdk 11 迁移到 jdk 17。但是我在 java 17 中不断遇到错误:

Exception in thread "main" java.time.format.DateTimeParseException: Text '09/18/2018 10:31:40 PM' could not be parsed at index 0
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2052)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)
at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:600)
at Main.convertToEpoch(Main.java:15)
at Main.getOrderTime(Main.java:54)
at Main.lambda$dateTest$0(Main.java:60)
at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4204)
at Main.dateTest(Main.java:60)
at Main.main(Main.java:71)

但是,我在 java 11 中没有收到此错误。示例代码如下:

public class Main {
public static Long convertToEpoch(String dateTime, String pattern) {
    System.out.println(ZoneId.systemDefault());
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault());
    return ZonedDateTime.parse(dateTime, dateTimeFormatter).toInstant().toEpochMilli();
}

private static Long getOrderTime(String orderSavedTime) {
    try {
        return convertToEpoch(orderSavedTime, "yyyy-M-d'T'H:m:sXXX");
    } catch (DateTimeParseException e) {
        System.out.println("unable to parse date in yyyy-M-d'T'H:m:sXXX  trying next format ");
    }
    try {
        //one space less
        return convertToEpoch(orderSavedTime, "MMM d yyyy h:m:s a");
    } catch (DateTimeParseException e) {
        System.out.println("unable to parse date in MMM d yyyy h:m:s a trying next format ");
    }

    try {
        return convertToEpoch(orderSavedTime, "M/d/yy h:m:s a");
    } catch (DateTimeParseException e) {
        System.out.println("unable to parse date in M/d/yy h:m:s a trying next format ");
    }
    try {
        return convertToEpoch(orderSavedTime, "M/d/yyyy h:m:s a");
    } catch (DateTimeParseException e) {
        System.out.println("unable to parse date in M/d/yyyy h:m:s a trying next format ");
    }

    try {
        return convertToEpoch(orderSavedTime, "yyyy-M-d H:m:s");
    } catch (DateTimeParseException e) {
        System.out.println("unable to parse date in yyyy-M-d H:m:s trying next format ");
    }

    try {
        return convertToEpoch(orderSavedTime, "MMM  d yyyy h:m:s:SSSa");
    } catch (DateTimeParseException e) {
        System.out.println("unable to parse date in yyyy-M-d H:m:s trying next format ");
    }

    return convertToEpoch(orderSavedTime, "MMM d yyyy h:m:s:SSSa");
}

public static void dateTest() {
    List<String> formats = Arrays.asList("09/18/2018 10:31:40 PM", "10/18/2018 3:39:24 AM", "9/18/2018 10:31:40 PM", "9/18/2018 3:39:24 PM", "9/18/2018 2:43:08 PM",
            "9/18/2018 5:09:05 PM", "09/09/2018 06:32:29 PM", "09/09/18 06:32:29 PM", "08/09/18 06:02:20 PM", "8/9/18 6:2:2 PM", "Nov  1 2018 12:00:00:000AM");
    formats.forEach(v -> System.out.println(v + " -> " + new Date(getOrderTime(v))));
    System.out.println("new form");
    formats = Arrays.asList("Sep 22 2014 10:33:55:555AM", "Sep 02 2014 2:3:5:555AM", "Sep 2 2014 2:3:05 AM", "Oct 12 2004 02:3:50 PM", "2018-09-08T00:00:00+05:30",
            "Nov  1 2018 12:00:00:000AM");
    formats.forEach(v -> System.out.println(
            v + " -> " + ZonedDateTime.ofInstant(Instant.ofEpochMilli(getOrderTime(v)), ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("MMM d yyyy h:m:s:SSSa"))));
    formats.forEach(v -> System.out.println(v + " -> " + ZonedDateTime.ofInstant(Instant.ofEpochMilli(getOrderTime(v)), ZoneId.systemDefault())));

}

public static void main(String[] args) {
    dateTest();
    }
}

java11 中的相同示例代码正常运行: 部分输出(用于第一个元素)

Asia/Kolkata
unable to parse date in yyyy-M-d'T'H:m:sXXX  trying next format 
Asia/Kolkata
unable to parse date in MMM d yyyy h:m:s a trying next format 
Asia/Kolkata
unable to parse date in M/d/yy h:m:s a trying next format 
Asia/Kolkata
09/18/2018 10:31:40 PM -> Tue Sep 18 22:31:40 IST 2018

它可能与 AM/PM 标记和区分大小写有关,但原始代码是遗留的,我不想做很多更改。

日期时间格式 java-11 java-17 datetimeformatter

评论

1赞 Holger 7/12/2023
尝试所有这些格式的方式,您总是会看到上次尝试的例外,该尝试已经在位置 0 处失败。如果您正在检查预期成功的匹配尝试的异常,则可以看到它在输入字符串中的哪个位置失败。
0赞 Anurator 7/12/2023
@Holger是的,我做到了,如果列表中的日期具有大写的 AM/PM,并且在小写的 am/pm 成功,则失败。我想知道为什么会发生这种情况,因为它在 Java11 中完美运行。此外,了解原因可能有助于我防止 java src 代码逻辑中出现任何问题。formats
1赞 Holger 7/13/2023
无法复制。偶数在格式化日期时间时生成大写的 AM/PM。当使用美国语言环境时,示例程序不会在 JDK 17 中失败。DateTimeFormatter
0赞 Anurator 7/14/2023
好的,@Holger这个问题仍然存在,因为我的系统默认值是亚洲/加尔各答(en_IN)作为区域设置。如果是,那么在不将我的语言环境切换到美国或英语的情况下,我该如何解决?我是 java 和 spring 的新手,如果您能告诉我为什么会发生这种情况或我从哪里知道它,那就太好了?

答:

1赞 Arvind Kumar Avinash 7/18/2023 #1

...有没有可能这个问题作为我的系统默认值仍然存在 是 ASIA/Kolkata (en_IN) 作为区域设置。如果是,那么无需切换我的 locale 设置为美国或英语,我该如何解决?

我强烈建议您始终使用始终敏感的对象指定 a。但是,如果您不想在这种情况下使用它,则可以使用 create 不区分大小写的 。LocaleDateTimeFormatterLocaleDateTimeFormatter

演示

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                .parseCaseInsensitive() // For case-insensitive (e.g. am, Am, AM) parsing
                .appendPattern("d MMM uuuu h:m a")
                .toFormatter();

        // Test
        Stream.of(
                "24 Oct 2016 7:31 pm",
                "24 Oct 2016 7:31 PM"
        ).forEach(s -> System.out.println(LocalDateTime.parse(s, dtf)));
    }
}

输出:

2016-10-24T19:31
2016-10-24T19:31

ONLINE DEMO

Trail: Date Time 了解有关新式日期时间 API 的更多信息。