Off The Point

human ⚯ engineer ⚯ musician

The Java 8 Date API is still a mess

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? Wrong.
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:
Duration.of(90, ChronoUnit.SECONDS).get(ChronoUnit.MILLIS))
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, SECONDS and NANOS. All other units throw an exception.
THIS CANNOT BE REAL This cannot be real. IT CANNOT BE REALLY SAYING WHAT IT SAYS. But it does. Here’s a screenshot: 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:
Throws: 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 I required.
Duration.of(90, ChronoUnit.SECONDS).toMillis();
So if you wanted to convert dynamically, you are required to write a big switch statement or a freaking if-cascade.

Next Post

Previous Post

Leave a Reply

© 2019 Off The Point

Theme by Anders Norén