Какие значения MIN / MAX будут работать как с ZonedDateTime, так и с Instant.toEpochMilli?
Я хочу использовать минимальные / максимальные значения времени, которые могут преобразовываться между ZonedDateTime
и Instant.toEpochMilli()
, для использования в качестве значений sentinel для фильтра / запроса.
пробовал:
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"));
это лучшее решение?
1 ответов
Instant.EPOCH
эквивалентно 1970-01-01T00:00Z
, поэтому я не уверен, что это хороший кандидат на минимальное значение (это зависит от ваших потребностей, конечно - если все ваши даты после 1970 года, тогда все будет хорошо).
преобразование Instant.MIN
и Instant.MAX
to ZonedDateTime
не работает все время, потому что в зависимости от смещения поля могут быть установлены на значения за пределами границ (как это произошло с годом, в вашем случае).
если вы хотите далекие даты, которые могут быть преобразованы в ZonedDateTime
и Instant
, вам не нужно использовать встроенные константы MIN / MAX, потому что они используют очень далекие даты (от лет, таких как -1000000000 до 1000000000), и эквивалент эпоха Милли значения для таких далеких дат намного больше (или ниже), чем пределы a 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.192 Z
maxInstant=+292278994-08-17T07:12: 55.807 Z
minZonedDateTime=-292275055-05- 16T16: 47: 04.192 Z
maxZonedDateTime=+292278994-08-17T07:12: 55.807 Z
и соответствующие значения для 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
to OffsetDateTime
используя atOffset
способ (например,minInstant.atOffset(ZoneOffset.UTC)
).
Примечания:
- вместо
ZoneId.of("Z")
, вы можете использовать константуZoneOffset.UTC
. На самом деле, если вы проверитеZoneId.of("Z").equals(ZoneOffset.UTC)
, в результатtrue
.
ДажеZoneId.of("Z") == ZoneOffset.UTC
тожеtrue
, так что оба действительно одно и то же. - в зависимости от значений вашего запроса вам не нужно использовать такие экстремальные даты. Вы можете установить минимум в 1900 году и максимум в 2900, например. Все зависит от вашего набора данных. Но, используя этот подход, будет хорошо, если ваша база данных может обрабатывать такие большие значения за год.