1

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 :)?

Sogawa-sps
  • 147
  • 10
  • 7
    no, not a bug - as [documented](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Instant.html#parse(java.lang.CharSequence)), `parse()` is using ISO-8601; and it [requires](https://en.wikipedia.org/wiki/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] ..., and it must be prefixed with a + or − sign*" - posted input string is missing the `+` sign – user16320675 Apr 15 '23 at 15:07
  • "_Did I find a bug in Java_" Anytime you ask this question, almost always the answer is NO. – Abhijit Sarkar Apr 15 '23 at 16:12

1 Answers1

10

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

user16320675
  • 135
  • 1
  • 3
  • 9
  • Thank you @user16320675, it's clear now. BTW, I wonder why it was decided not to allow a "+" for dates within the 0000..9999 range (say "+1300-01-01T00:00:00Z" is unparseable), from my point it would make more sense. But it is what it is. – Sogawa-sps Apr 15 '23 at 17:24