DateTimeExt { public static String toRateString(long interval, long itemsPerInterval, TimeUnit timeUnit, String rateType) { TimeUnit matchedTimeUnit = timeUnit; for (TimeUnit nextTimeUnit : TimeUnit.values()) { double ratio = nextTimeUnit.toNanos(1) / (double) timeUnit.toNanos(1); double rate = itemsPerInterval / (double) interval * ratio; if (rate >= 0.1) { matchedTimeUnit = nextTimeUnit; break; } } double ratio = matchedTimeUnit.toNanos(1) / (double) timeUnit.toNanos(1); double rate = itemsPerInterval / (double) interval * ratio; return String.format("%.2f %s/%s", rate, rateType, toTimeUnitAbbreviation(matchedTimeUnit)); } private  DateTimeExt(); static ZoneId toZoneId(String timeZoneName); static ZoneOffset toZoneOffset(String timeZoneName); static String toUtcDateTimeString(long msSinceEpoch); static String toLocalDateTimeString(long msSinceEpoch); static String toTimeUnitAbbreviation(TimeUnit timeUnit); static String toTimeUnitString(Duration duration); static String toTimeUnitString(long timeMs); static String toRateString(long interval, long itemsPerInterval, TimeUnit timeUnit, String rateType);  }
@Test public void testToRateString() { assertThat(toRateString(1, 1, TimeUnit.MILLISECONDS, "action")).isEqualTo("1.00 action/ms"); assertThat(toRateString(60, 5, TimeUnit.SECONDS, "action")).isEqualTo("5.00 action/min"); }