Избегайте арифметического переполнения Instant.toEpochMilli()

Вызов JDK Instant.toEpochMilli() может привести к арифметическому переполнению Instant.MAX.toEpochMilli() или же Instant.MIN.toEpochMilli()). Я ищу простой способ избежать арифметического переполнения и просто использовать Long.MAX_VALUE, Вот мой текущий код.

long seconds, millis;

seconds = deadline.getEpochSecond();

if (seconds > Long.MAX_VALUE / 1000 - 1)
   millis = Long.MAX_VALUE;
else if (seconds < Long.MIN_VALUE / 1000 + 1)
   millis = Long.MIN_VALUE;
else
   millis = deadline.toEpochMilli();

Кажется, что должен быть более ясный / ясный способ реализовать это. Как бы вы реализовали эту логику?

Я должен беспокоиться о переполнении / потере, потому что Instant.MAX а также Instant.MIN передаются в метод, где этот код находится.

2 ответа

Решение

Ты можешь использовать java.lang.Math.addExact, Это бросит ArithmeticException если происходит переполнение. Это было добавлено в Java 8.

РЕДАКТИРОВАТЬ

Хорошо, подумав над этим вопросом, думаю, у меня есть хорошее решение:

private Instant capped(Instant instant) {
    Instant[] instants = {Instant.ofEpochMilli(Long.MIN_VALUE), instant, Instant.ofEpochMilli(Long.MAX_VALUE)};
    Arrays.sort(instants);
    return instants[1];
}

Этот метод вернет момент, который никогда не будет переполнен toEpochMilli(),

Упрощение вашей логики для:

millis = capped(deadline).toEpochMilli();

toEpochMilli выдает исключение в случае переполнения, поэтому вы можете просто перехватить это исключение:

try {
  millis = deadline.toEpochMillis();
} catch (AritmeticException ignore) {
  millis = deadline.getEpochSecond() < 0 ? Long.MIN_VALUE : Long.MAX_VALUE;
}

Этот код проще и безопаснее, чем написано в вопросе. Это безопаснее, потому что он не пытается повторно реализовать граничную логику внутри toEpochMillis(),

Может возникнуть проблема с производительностью при выдаче и отлове исключений. Это зависит от того, как часто выдается исключение. Если исключение выдается большую часть времени, это будет работать хуже, если JVM не сможет оптимизировать это. Если исключение выдается редко, то производительность будет хорошей.

JVM может оптимизировать это, но, возможно, нет.

Другие вопросы по тегам