Time for non-Time Lords – Part 4

Time is hard. Any developer who tells you differently is either lying; thinks they understand it when they really don’t; or is a bona fide Time Lord. In this series we’ll explore some of the issues that time can pose, and take a look at some tools that we can use to help make time handling a little easier.

Previously we’ve looked at the basic use of the JSR 310 time and date APIs, what other benefits do we get? Remember those tricky leap year issues we looked at in an earlier article? Let’s take a look at whether they are going to be an issue if we use JSR 310.

To help us explore this we can actually use the Year class which, strangely enough, represents a year. This actually has a rather useful isLeap() method which does precisely what we need. Here we create a list of different years and display whether or not they are leap years:

2000 is evenly divisible by 4, is evenly divisible by 100 and is evenly divisible by 400 so is a leap year

1900 is evenly divisible by 4, is evenly divisible by 100 and is not evenly divisible by 400 so is not a leap year

2100 is evenly divisible by 4, is evenly divisible by 100 and is not evenly divisible by 400 so is not a leap year

2400 is evenly divisible by 4, is evenly divisible by 100 and is evenly divisible by 400 so is a leap year

So we get leap year handling correctly done for us using these APIs.

The other thing we looked at earlier was using time units to make our APIs easier to understand by allowing the caller to specify the units of the time value it is supplying. The approach we looked at earlier is perfectly valid and there is absolutely no reason to change that approach. However, JSR 310 does provide a similar mechanism for specifying time units.

ChronoUnit is an enum containing various units, and each is resolvable to a Duration. We can display all of these in nanoseconds:

Resolving the unit to a duration enables us to convert to whatever units we like – so the caller specifies the units it provides and is agnostic about the units required by the method implementation; and the method implementation is agnostic about the units it is called with, but has a simple mechanism to convert them to the units it requires.