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:

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.