Home > Back-end >  Why "-190732550-MM-ddTHH:mm:ss.SSSZ" datetime does not fail to parse
Why "-190732550-MM-ddTHH:mm:ss.SSSZ" datetime does not fail to parse

Time:04-17

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?

CodePudding user response:

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.

  • Related