This is the method toNanos
in class Duration
public long toNanos() {
long tempSeconds = seconds;
long tempNanos = nanos;
// TODO: Here makes me confused
if (tempSeconds < 0) {
// change the seconds and nano value to
// handle Long.MIN_VALUE case
tempSeconds = tempSeconds + 1;
tempNanos = tempNanos - NANOS_PER_SECOND;
}
long totalNanos = Math.multiplyExact(tempSeconds, NANOS_PER_SECOND);
totalNanos = Math.addExact(totalNanos, tempNanos);
return totalNanos;
}
I couldn't understand why need to do extra work when seconds is negative.
Positive numbers' max is 2^63-1
and negative numbers' min is 2^63
, looks like it transfer -2^63s,-1ns
to -2^63+1s,1000_000_000-1ns
, but it has to particate in calculate eventually. In my view this is meaningless because Math.multiplyExact
and Math.addExact
will throw an Exception when numbers overflow, it doesn't change not matter the judgement existed or not
The extra work is needed for the case Duration.ofNanos(Long.MIN_VALUE)
(and some more cases which result in the same number of seconds).
Duration.ofNanos(Long.MIN_VALUE)
is stored as seconds=-9223372037 and nanos=145224192.
The simple calculation seconds*1_000_000_000
would underflow the range of long values (and therefore the naive Math.multiplyExact(seconds, NANOS_PER_SECOND)
would throw an exception). But Duration.ofNanos(Long.MIN_VALUE).toNanos()
should not throw an exception, it should return Long.MIN_VALUE
.
They could have written the condition as if (tempSeconds <= -9223372037) { ... }
and it would give the same results (i.e. throw for the same values of seconds and nanos) but such a constant is harder to maintain.