为什么“-190732550-MM-ddTHH:mm:ss.SSSZ”datetime不会解析失败

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

考虑以下片段:

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());

输出:

String: -190732550-05-25T15:14:51.136Z
ZonedDateTime: -190732550-05-25T15:14:51.136Z
EpochMilli: -6019000079877908864

我预计上面会抛出 java.time.format.DateTimeParseException

编辑

"190732550-05-25T15:14:51.136Z" 抛出 java.time.format.DateTimeParseException。不应该也有效吗?

tl;博士

这个:

Instant.parse( "-190732550-05-25T15:14:51.136Z" )

…成功是因为你输入的几亿年在那个class.

的+/- 10亿年的范围内

-1,000,000,000 < -190,732,550 < +1,000,000,000

使用 Instant class 解析以 Z 结尾的输入字符串,这意味着与 UTC 的偏移量为零 hours-minutes-seconds。不涉及时区,因此不需要 ZonedDateTime.

Instant instant = Instant.parse( "-190732550-05-25T15:14:51.136Z" ) ;

这个输入确实会被解析成功。您提供的年份位于该数据类型的可能值范围内。

Instant 的最小值在预定义常量 Instant.MIN 中表示。引用 Javadoc:

The minimum supported Instant, '-1000000000-01-01T00:00Z'.

也就是当年-1,000,000,000(十亿)。

你输入的年份只有-190,732,550(亿)。因此,您的值符合 +/- 十亿年的可接受范围。

Instant class 当前实现为一对 64 位 long 整数。一个是自 1970 UTC 的第一时刻以来的整秒数。另一个是小数秒中的纳秒计数。所以这个 class 能够支持范围很广的值。

积极性

请注意 positive-numbered 超过四位数的年份必须在前面加上一个加号字符。

为预定义常量 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 引用 Javadoc(强调我的):

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.

这成功了:

Instant.parse( "+190732550-05-25T15:14:51.136Z" ) 

... 而这失败了:

Instant.parse( "190732550-05-25T15:14:51.136Z" ) 

看到这个code run live at IdeOne.com