Search code examples
javatimearithmetic-overflow

Avoid Instant.toEpochMilli() Arithmetic Overflow


Calling the JDKs Instant.toEpochMilli() could result in an arithmetic overflow/underflow (e.g. Instant.MAX.toEpochMilli() or Instant.MIN.toEpochMilli()). I am looking for a simple way to avoid the arithmetic overflow and simply use Long.MAX_VALUE. Here's my current code.

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

It seems like there has to be a cleaner/clearer way to implement this. How would you implement this logic?

I have to be concerned about overflow/underflow because Instant.MAX and Instant.MIN are passed to the method where this code resides.


Solution

  • You can use java.lang.Math.addExact. It will throw an ArithmeticException if overflow occurs. It was added in Java 8.

    EDIT

    Ok, thinking about this question some more, I think I have a nice solution :

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

    This method will return an Instant that will never overflow on toEpochMilli().

    Simplifying your logic to :

    millis = capped(deadline).toEpochMilli();