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.