哪些 MIN/MAX 值适用于 ZonedDateTime 和 Instant.toEpochMilli?
What MIN/MAX values will work with both ZonedDateTime and Instant.toEpochMilli?
我想使用 MIN/MAX 可以在 ZonedDateTime
和 Instant.toEpochMilli()
之间转换的时间值,用作 filter/query.[=21= 的标记值]
我试过:
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"))
但是 returns 与上一个异常相同。
最后我尝试了以下方法,它似乎有效:
ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of("Z"));
ZonedDateTime.ofInstant(Instant.EPOCH.plusMillis(Long.MAX_VALUE), ZoneId.of("Z"));
这是最好的解决方案吗?
Instant.EPOCH
等同于 1970-01-01T00:00Z
,所以我不确定它是否适合最小值(当然,这取决于您的需要 - 如果您的所有日期都在1970年,那就好了。
将 Instant.MIN
和 Instant.MAX
转换为 ZonedDateTime
并不总是有效,因为根据偏移量,字段可以设置为超出边界的值(就像发生在年,在你的情况下)。
如果你想要可以转换为 ZonedDateTime
和 Instant
的遥远的日期,你不需要使用内置的 MIN/MAX 常量,因为它们使用非常远日期(从 -1000000000 到 1000000000 这样的年份),以及此类远日期的等效 epoch milli 值远大于(或小于)long
值的限制.
因为您需要使用 toEpochMilli()
并且它 returns 和 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
以及纪元毫的相应值:
System.out.println("minInstant millis=" + minInstant.toEpochMilli());
System.out.println("maxInstant millis=" + maxInstant.toEpochMilli());
minInstant millis=-9223372036854775808
maxInstant millis=9223372036854775807
我使用 ZoneOffset.UTC
而不是某个特定的时区,因为这些日期到目前为止都在 past/future 中,几个小时的偏移不会造成太大影响。而且它们都将等同于相同的毫秒瞬间。
您也可以使用 atOffset
方法(例如 minInstant.atOffset(ZoneOffset.UTC)
)将 Instant
转换为 OffsetDateTime
。
备注:
- 而不是
ZoneId.of("Z")
,您可以使用常量 ZoneOffset.UTC
。实际上,如果你检查ZoneId.of("Z").equals(ZoneOffset.UTC)
,结果是true
。
甚至 ZoneId.of("Z") == ZoneOffset.UTC
也是 true
,所以两者实际上是一回事。
- 根据您的查询值,您不需要使用这么远的日期。例如,您可以将最小值设置为 1900 年,将最大值设置为 2900 年。这完全取决于您的数据集。但是,如果您的数据库可以处理一年中如此大的值,那么使用上述方法就可以了。
我想使用 MIN/MAX 可以在 ZonedDateTime
和 Instant.toEpochMilli()
之间转换的时间值,用作 filter/query.[=21= 的标记值]
我试过:
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"))
但是 returns 与上一个异常相同。
最后我尝试了以下方法,它似乎有效:
ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of("Z"));
ZonedDateTime.ofInstant(Instant.EPOCH.plusMillis(Long.MAX_VALUE), ZoneId.of("Z"));
这是最好的解决方案吗?
Instant.EPOCH
等同于 1970-01-01T00:00Z
,所以我不确定它是否适合最小值(当然,这取决于您的需要 - 如果您的所有日期都在1970年,那就好了。
将 Instant.MIN
和 Instant.MAX
转换为 ZonedDateTime
并不总是有效,因为根据偏移量,字段可以设置为超出边界的值(就像发生在年,在你的情况下)。
如果你想要可以转换为 ZonedDateTime
和 Instant
的遥远的日期,你不需要使用内置的 MIN/MAX 常量,因为它们使用非常远日期(从 -1000000000 到 1000000000 这样的年份),以及此类远日期的等效 epoch milli 值远大于(或小于)long
值的限制.
因为您需要使用 toEpochMilli()
并且它 returns 和 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
以及纪元毫的相应值:
System.out.println("minInstant millis=" + minInstant.toEpochMilli());
System.out.println("maxInstant millis=" + maxInstant.toEpochMilli());
minInstant millis=-9223372036854775808
maxInstant millis=9223372036854775807
我使用 ZoneOffset.UTC
而不是某个特定的时区,因为这些日期到目前为止都在 past/future 中,几个小时的偏移不会造成太大影响。而且它们都将等同于相同的毫秒瞬间。
您也可以使用 atOffset
方法(例如 minInstant.atOffset(ZoneOffset.UTC)
)将 Instant
转换为 OffsetDateTime
。
备注:
- 而不是
ZoneId.of("Z")
,您可以使用常量ZoneOffset.UTC
。实际上,如果你检查ZoneId.of("Z").equals(ZoneOffset.UTC)
,结果是true
。
甚至ZoneId.of("Z") == ZoneOffset.UTC
也是true
,所以两者实际上是一回事。 - 根据您的查询值,您不需要使用这么远的日期。例如,您可以将最小值设置为 1900 年,将最大值设置为 2900 年。这完全取决于您的数据集。但是,如果您的数据库可以处理一年中如此大的值,那么使用上述方法就可以了。