Format a Date interval in Java

Format a Date interval in Java

At the time of this writing, there are a gazillion ways to print dates in Java:

  • SimpleDateFormat (deprecated, use java.time instead)
  • Joda time (deprecated, use java.time instead)
  • Threeten (deprecated, use java.time instead)
  • Java 8 Date/Time API (also known as java.time) <== This. You should be using this. Use this.

The problem is, how do we print a date interval in Java? None of these libraries supports this particular use case. Duration is not a date interval, and neither is Period. ZonedDateTime.format is great, but only supports a single date. There are no libraries out there to format an interval of dates, as far as we could see.

Enter String.format, described in the javadoc for Formatter. This is a method typically used to interpolate values inside Strings:

String.format("foo %s", "bar"); // return "foo bar"

This method also supports internationalization when passing a Locale as first argument. You know where we are going, right?

var start = parseISO8601("2020-01-02T10:10:00Z");
var end = parseISO8601("2020-02-03T10:10:00Z");

Locale locale = Locale.ENGLISH;

// please don't do this in real code - use .properties instead
String pattern = "en".equals(locale.getLanguage())? 
  // "January 2 - February 3, 2020"
  "%1$tB %1$te - %2$tB %2$te, %1$tY",

  // 2 de enero - 3 de febrero de 2020
  "%1$te de %1$tB - de %2$te %2$tB de %1$tY";

return String.format(locale, pattern, start, end);

According to the docs, %1$te can be used to indicate the following:

%1$ is the first argument, t indicates that it's a date, e tells to extract the day of the month

The same date can be used more than once, and the order can be rearranged depending on the locale. The rest is playing with other options: extract the year, month names, whatever. Go crazy.