Error parsing time with two decimal digits in Java 17, but succeeds in Java 8
Asked Answered
F

1

10

The following code snippet runs without error in Java 8. However, when I run the same code in Java 17 it fails.

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main2 {
    public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH[:mm[:ss[.SSS]]]X");
        OffsetDateTime offSetDateTime = OffsetDateTime.parse("2021-10-09T08:59:00.00Z", formatter);
        System.out.println(offSetDateTime);
    }
}

Output when run on Java 17:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2021-10-09T08:59:00.00Z' could not be parsed at index 19
    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.OffsetDateTime.parse(OffsetDateTime.java:404)
    at Main2.main(Main2.java:9)

However, if I run the same code against Java 8 it gives the following result:

2021-10-09T08:59Z

If I change the test data from "2021-10-09T08:59:00.00Z" to "2021-10-09T08:59:00.000Z", it works in Java 17. Any idea what changes in Java 17 has causes it it fail?

Financier answered 30/1 at 18:5 Comment(1)
Looks like a more strict check. If you remove one of S it works for meNeolith
B
10

This behaviour seems to be caused by the fix for JDK-8230136.

JDK-8230136 is the issue that the fraction-of-second field does not check its minimum width. If you do appendFraction(NANO_OF_SECOND, 3, 3, false) in a DateTimeFormatterBuilder, 1, 2, or 3 digits will all be accepted by that field.

DateTimeFormatter uses DateTimeFormatterBuilder under the hood, and so it is also affected. The SSS in your pattern eventually leads to a call like appendFraction(NANO_OF_SECOND, 3, 3, false) on a DateTimeFormatterBuilder.

If you need the old behaviour, you can call appendFraction with your own minimum digit count.

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .appendPattern("yyyy-MM-dd'T'HH[:mm[:ss[")
        .appendFraction(ChronoField.NANO_OF_SECOND, 1, 3, true)
        .appendPattern("]]]X")
        .toFormatter();
Breazeale answered 30/1 at 19:54 Comment(3)
A relevant spec quote that was fixed by that issue: "When parsing in strict mode, the number of parsed digits must be between the minimum and maximum width."Hypocrite
@M.Justin Yeah, I saw that too, but didn't manage to find which page that quote is from. I thought it was from DateTimeFormatter, but I didn't find it there.Breazeale
The quote's from DateTimeFormatterBuilder.appendFraction.Hypocrite

© 2022 - 2024 — McMap. All rights reserved.