javajava-timejava.time.instant

java.time.Instant - error while parsing a huge date


I'm trying to parse a really large date (but still way less than Instant.MAX) using the Instant.parse method but getting an error.

String input = "78000000-01-01T00:00:00Z";
Instant instant = Instant.parse(input);

Exception:

Exception in thread "main" java.time.format.DateTimeParseException: Text '78000000-01-01T00:00:00Z' could not be parsed at index 0
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2106)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:2008)
at java.base/java.time.Instant.parse(Instant.java:399)

The BC date "-78000000-01-01T00:00:00Z" is parsed ok.

Did I find a bug in Java :)?


Solution

  • Feature, not a bug

    No, it is not a bug - is working as specified!

    From documentation of parse():

    is parsed using DateTimeFormatter.ISO_INSTANT

    and from ISO_INSTANT

    returns an immutable formatter capable of formatting and parsing the ISO-8601 instant format

    ISO_INSTANT refers to ISO_OFFSET_DATE_TIME to ISO_LOCAL_DATE_TIME to ISO_LOCAL_DATE. The last one says:

    • Four digits or more for the year. Years in the range 0000 to 9999
      will be pre-padded by zero to ensure four digits. Years outside that
      range will have a prefixed positive or negative symbol.

    This is meant to imply that years to be parsed must abide by the mentioned format too.

    Finally, from Wikipedia for ISO-8601 (Years):

    To represent years before 0000 or after 9999, the standard also permits the expansion of the year representation .... An expanded year representation [±YYYYY] must have an agreed-upon number of extra year digits beyond the four-digit minimum, and it must be prefixed with a + or − sign.

    Emphasis mine


    The input string "78000000-01-01T00:00:00Z" is missing that + sign, while "-78000000-01-01T00:00:00Z" correctly starts with a - sign.

    The input "+78000000-01-01T00:00:00Z" is parsed without error.


    Hint: you can check the format by formatting a test date/time/... before parsing.
    For example:

    var test = Instant.from(OffsetDateTime.of(78000000, 1, 1, 0, 0, 0, 0,ZoneOffset.UTC));
    System.out.println(test.toString());  // or using any relevant formatter
    

    Output:

    +78000000-01-01T00:00:00Z