Do you remember how everybody was hyped about the new date and time APIs introduced in Java 8?
Yes, I was hyped too, although I was using jodatime
wherever I could anyway.
Now this was a while back and at the time of this writing, Java 10 is out and the latest (or at least a fairly current) release is
java version "10.0.1" 2018-04-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)
so we all have even saner APIs to deal with dates and times, right?
SO, SO, WRONG
The unsuspecting Dev
Today I was configuring some timeouts at work, and I though to myself
Why not be really explicit about what values and units are used?
It is 2018 and I don’t want or need to see lines like
long timeoutmillis = (long) 420_000 * COMPANY_INTERNAL_TIME_FACTOR * 1e-3 - 1
so, with the help of my trusty IDE autocompletion, I arrived at something much more pleasing to the eye:
Looks pretty good, no? It’s quite explicit about what values are used and about the units they have.
Not so fast. A RuntimeException in the logs.
java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Millis
Surely, that must be some kind of silly error on my side. A quick check with the documentation
confirmed that it was much, much worse.
It says, and I kid you not,
This returns a value for each of the two supported units,
NANOS. All other units throw an exception.
This cannot be real. IT CANNOT BE REALLY SAYING WHAT IT SAYS. But it does. Here’s a screenshot:
API Design at it’s finest
So somebody, actually multiple people, looked at the proposal and said,
why, yes, let this API accept only 2 units and throw exceptions otherwise. That, right here, is an API worthy of bringing into our specification.
And that’s why, folks, we cannot have nice APIs, not even now, in 2000-freaking-18.
But wait, I have another goodie for you. Maybe you saw it already:
Calling this method might throw 2 different exceptions:
DateTimeException – if the unit is not supported
UnsupportedTemporalTypeException – if the unit is not supported
Um, which will it throw?
Anyway, Duration is actually able to do the conversion
So if you wanted to convert dynamically, you are required to write a big switch statement or a freaking if-cascade.