Simplify Time Intervals in Java With TimeUnit

Simplify Time Intervals in Java With TimeUnit

In Java, like most programming languages, it is fairly common to represent and pass around time interval lengths as a number of milliseconds.  This how most hardware thinks of time under the covers, anyway.  It’s very easy to get a millisecond representation from any Java date or time object, and you can always get the current time from System.currentTimeMillis().   Therefore, milliseconds are a “universal language” that is often used in API’s, to avoid worrying about who’s using the Java 8 time library vs. pre-Java 8 libraries vs. Joda-Time or whatever.

It is common to pass time intervals as a millisecond value, but it is less common for humans to think about time at that level of granularity.  If you want a scheduled task to execute once every ten minutes, then it’s a bit awkward to think of that in terms of “once every 600,000 millseconds”.  When intervals span periods of hours, days, weeks and beyond, the mental conversion starts to become ridiculous.

The Old Pattern

Therefore, this is a common pattern that you will often see in Java code:

Java code sample without TimeUnit

...
static final long EVERY_TWO_WEEKS_IN_MILLIS =
    2 * 7 * 24 * 60 * 60 * 1000;
...

Don’t do this!  Sure, this might be more intuitive and easier to change than 1,209,600,000.  However, it’s still very unwieldy, and is simply begging for someone to accidentally introduce an “off-by-an-order-of-magnitude” bug at some point.  Those are never any fun!

Using TimeUnit Instead

Java 5 introduced a better way of doing this, with the java.util.concurrent.TimeUnit enum.  Since that’s been around for years now, I’m always surprised during code reviews to encounter developers still using the old pattern.  I suppose this is something that everyone has to deal with once in awhile, but doesn’t come up often enough to think much about it.

The TimeUnit enum has constants for MILLISECONDS, SECONDS, HOURS, etc.  Pretty much every time unit you might reasonably use, up to the DAY level of granularity.

More importantly, TimeUnit contains toXXX() methods for converting from a given time unit to another.  There is a method corresponding to each constant (e.g. toMillis(), toSeconds(), toHours(), etc).

Putting these together, you can now represent the number of milliseconds in a time interval with greater readability and less chance of bugs, by using this pattern:

Java code sample with TimeUnit

...
static final long EVERY_TWO_WEEKS_IN_MILLIS =
    TimeUnit.DAYS.toMillis(14);
...

It’s visually obviously what’s happening here, and very easy to change later if a different interval is needed.  In fact, if this value is only used in one place then there’s really no need for assigning it to a class-level constant at all.  That approach is commonly used in old-school Java, so that the name of the constant could give some visual indication of the value.  With the TimeUnit construct, this information is already apparent.