Time

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:

If we run this we get the following output:

To recap on the reasoning behind this:

  • 2016 is evenly divisible by 4 so is a leap year
  • 2017 is not evenly divisible by 4 so is not a leap year
  • 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:

The reason for the filter is that the duration in nanoseconds is stored in a Long and this overflows if we try and convert a MILLENNIA or larger duration to nanoseconds.

The output of this is:

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.

Let’s alter our earlier example to use ChronoUnit instead of TimeUnit:

The caller is almost identical – we just change second argument to a ChronoUnit instead of a TimeUnit.

The implementation of this method is also pretty straightforward:

We get the Duration for the unit, convert that to milliseconds (the value that we use internally), and multiply this by the number of units.

I will re-iterate that this offers no benefits over TimeUnit other than being consistent in the use of JSR 310 APIs.

So far we’ve ignored an important aspect of handling date and time values: Timezones. In the final article in this series we’ll take a look at that.

The source code for this article is available here.

© 2017, Mark Allison. All rights reserved.

CC BY-NC-SA 4.0 Time for non-Time Lords – Part 4 by Styling Android is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Permissions beyond the scope of this license may be available at http://blog.stylingandroid.com/license-information.

Leave a Reply

Your email address will not be published. Required fields are marked *