Durations in existing JDK APIs
Martin Buchholz
martinrb at google.com
Tue Jun 5 03:52:26 UTC 2018
Looks like if you switch representation for negative Duration, much of the
hair goes away.
This version also optimizes for NANOSECONDS, which is very likely to be the
target in practice:
public long convert(Duration duration) {
long secs = duration.getSeconds();
int nano = duration.getNano();
if (secs < 0 && nano > 0) {
// use representation compatible with integer division
secs++;
nano -= SECOND_SCALE;
}
final long s;
if ((s = scale) >= SECOND_SCALE)
return (s == SECOND_SCALE) ? secs : secs / secRatio;
long val = secs * secRatio + ((s == NANO_SCALE) ? nano : nano / s);
return ((secs | nano) >= 0)
? ((secs > maxSecs || val < 0) ? Long.MAX_VALUE : val)
: ((secs < -maxSecs || val > 0) ? Long.MIN_VALUE : val);
}
On Mon, Jun 4, 2018 at 2:47 PM, Martin Buchholz <martinrb at google.com> wrote:
> TimeUnit#toDuration is gone.
>
> Here's a non-strawman attempt at TimeUnit#convert(Duration).
> I was astonished how hard it was to get this really correct instead of
> merely mostly correct.
> For negative numbers, the long/int representation of Duration is sort-of a
> "floored" division instead of java's default "truncating" division.
>
> public long convert(Duration duration) {
> final long secs = duration.getSeconds();
> final int nano = duration.getNano();
> final long s, candidate;
> if ((s = scale) == SECOND_SCALE)
> return (secs < 0 && nano > 0) ? secs + 1 : secs;
> if (s > SECOND_SCALE) {
> long div = secs / secRatio;
> if (secs < 0 && nano > 0 && div * secRatio == secs)
> div++;
> return div;
> }
> return (secs >= 0)
> ? ((secs > maxSecs
> || (candidate = secs * secRatio + nano / s) < 0)
> ? Long.MAX_VALUE : candidate)
> : ((secs < - maxSecs - 1
> || (candidate = secs * secRatio + (nano + s - 1) / s) > 0)
> ? Long.MIN_VALUE : candidate);
> }
>
>
More information about the core-libs-dev
mailing list