'Why "-190732550-MM-ddTHH:mm:ss.SSSZ" datetime does not fail to parse
Consider the following snippet:
String dateTimeStr = "-190732550-05-25T15:14:51.136Z";
ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeStr).withZoneSameInstant(ZoneOffset.UTC);
log.info("String: {}", dateTimeStr);
log.info("ZonedDateTime: {}", dateTime);
log.info("EpochMilli: {}", dateTime.toInstant().toEpochMilli());
Output:
String: -190732550-05-25T15:14:51.136Z
ZonedDateTime: -190732550-05-25T15:14:51.136Z
EpochMilli: -6019000079877908864
I expected the above would throw java.time.format.DateTimeParseException.
Edit
"190732550-05-25T15:14:51.136Z" throws java.time.format.DateTimeParseException. Shouldn't be valid too?
Solution 1:[1]
tl;dr
This:
Instant.parse( "-190732550-05-25T15:14:51.136Z" )
… succeeds because your input of a few hundreds of millions of years lies within the range of +/- one billion years in that class.
-1,000,000,000 < -190,732,550 < +1,000,000,000
Use Instant class to parse an input string ending in Z, which means an offset from UTC of zero hours-minutes-seconds. No time zone involved, so no need for ZonedDateTime.
Instant instant = Instant.parse( "-190732550-05-25T15:14:51.136Z" ) ;
This input will indeed be parsed successfully. You are supplying a year that lies within the range of possible values for that data type.
The minimum value for Instant is represented in the predefined constant Instant.MIN. To quote the Javadoc:
The minimum supported Instant, '-1000000000-01-01T00:00Z'.
That is the year -1,000,000,000 (one billion).
You input year is only -190,732,550 (hundreds of millions). So your value fits within the accepted range of +/- one billion years.
The Instant class is currently implemented as a pair of 64-bit long integers. One is for a number of whole seconds since the first moment of 1970 UTC. The other is for a count of nanoseconds in the fractional second. So this class is capable of supporting a wide range of values.
Positivity
Note that positive-numbered years with more than four digits must prepend a PLUS SIGN character.
To quote the Javadoc for the predefined constant DateTimeFormatter named ISO_LOCAL_DATE, which is used by ISO_LOCAL_DATE_TIME, which is used by ISO_OFFSET_DATE_TIME, which is used by ISO_INSTANT when calling Instant.parse (emphasis mine):
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 succeeds:
Instant.parse( "+190732550-05-25T15:14:51.136Z" )
… whereas this fails:
Instant.parse( "190732550-05-25T15:14:51.136Z" )
See this code run live at IdeOne.com.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
