我想使用可在ZonedDateTime
和Instant.toEpochMilli()
之间转换的MIN / MAX时间值,以用作过滤器/查询的标记值。
我试过了:
OffsetDateTime.MIN.toInstant().toEpochMilli();
OffsetDateTime.MAX.toInstant().toEpochMilli();
但我得到了这个例外:
java.lang.ArithmeticException: long overflow
at java.lang.Math.multiplyExact(Math.java:892)
at java.time.Instant.toEpochMilli(Instant.java:1237)
然后我尝试了这个:
ZonedDateTime.ofInstant(Instant.MIN, ZoneId.systemDefault());
ZonedDateTime.ofInstant(Instant.MAX, ZoneId.systemDefault());
然后我得到了这个例外:
java.time.DateTimeException: Invalid value for Year (valid values -999999999 - 999999999): -1000000001
at java.time.temporal.ValueRange.checkValidIntValue(ValueRange.java:330)
at java.time.temporal.ChronoField.checkValidIntValue(ChronoField.java:722)
at java.time.LocalDate.ofEpochDay(LocalDate.java:341)
at java.time.LocalDateTime.ofEpochSecond(LocalDateTime.java:422)
at java.time.ZonedDateTime.create(ZonedDateTime.java:456)
at java.time.ZonedDateTime.ofInstant(ZonedDateTime.java:409)
我也试过' Z' ZoneId
:
ZonedDateTime.ofInstant(Instant.MIN, ZoneId.of("Z"))
但是返回与上一个相同的异常。
最后我尝试了以下内容,似乎有效:
ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of("Z"));
ZonedDateTime.ofInstant(Instant.EPOCH.plusMillis(Long.MAX_VALUE), ZoneId.of("Z"));
这是最好的解决方案吗?
答案 0 :(得分:13)
Instant.EPOCH
相当于1970-01-01T00:00Z
,所以我不确定它是否是最小值的合适候选者(当然,这取决于您的需求 - 如果所有日期都在1970年以后,那就没事了。
将Instant.MIN
和Instant.MAX
转换为ZonedDateTime
不会一直有效,因为根据偏移量,字段可以设置为超出边界的值(就像年份一样,在你的情况下)。
如果您想要可以转换为ZonedDateTime
和Instant
的远距离日期,则不需要使用内置的MIN / MAX常量,因为它们使用非常远的日期(来自如年 - 例如-1000000000到1000000000),这些远距离日期的等效 epoch milli 值远大于(或低于)long
值的限制。
当您需要使用toEpochMilli()
并返回long
时,您必须保持在long
值的限制之间:
Instant minInstant = Instant.ofEpochMilli(Long.MIN_VALUE);
Instant maxInstant = Instant.ofEpochMilli(Long.MAX_VALUE);
ZonedDateTime minZonedDateTime = minInstant.atZone(ZoneOffset.UTC);
ZonedDateTime maxZonedDateTime = maxInstant.atZone(ZoneOffset.UTC);
各自的值为:
minInstant = -292275055-05-16T16:47:04.192Z
maxInstant = + 292278994-08-17T07:12:55.807Z
minZonedDateTime = -292275055-05-16T16:47:04.192Z
maxZonedDateTime = + 292278994-08-17T07:12:55.807Z
epoch milli的相应值:
System.out.println("minInstant millis=" + minInstant.toEpochMilli());
System.out.println("maxInstant millis=" + maxInstant.toEpochMilli());
minInstant millis = -9223372036854775808
maxInstant millis = 9223372036854775807
我使用了ZoneOffset.UTC
而不是某个特定的时区,因为这些日期在过去/未来到目前为止,几个小时的偏移不会产生太大的影响。而且无论如何它们都将相同于毫秒级。
您还可以使用Instant
方法将OffsetDateTime
转换为atOffset
(例如minInstant.atOffset(ZoneOffset.UTC)
)。
备注强>:
ZoneId.of("Z")
,您可以使用常量ZoneOffset.UTC
。实际上,如果您选中ZoneId.of("Z").equals(ZoneOffset.UTC)
,则结果为true
即使ZoneId.of("Z") == ZoneOffset.UTC
也是true
,所以两者都是一样的。