Instant supports only time-based ChronoUnit values and ChronoUnit.DAYS. Passing another ChronoUnit value to its arithmetic methods causes an UnsupportedTemporalTypeException when the unit is evaluated.

Why is this an issue?

An Instant represents a point on the timeline as a number of seconds and nanoseconds from the epoch. It does not define how date-based ChronoUnit values such as MONTHS or YEARS apply to its timeline. Custom TemporalUnit implementations may define their own behavior.

The plus(long, TemporalUnit), minus(long, TemporalUnit), and until(Temporal, TemporalUnit) methods support the following ChronoUnit values:

Using WEEKS, MONTHS, YEARS, DECADES, CENTURIES, MILLENNIA, ERAS, or FOREVER with these methods throws an UnsupportedTemporalTypeException when the unit is evaluated. The operation cannot produce a result, which can interrupt date and time processing in the application.

Exceptions

This rule reports only direct ChronoUnit constants. It does not track a constant stored in a variable.

Custom TemporalUnit implementations are not reported because Instant delegates the operation to them. The plus(TemporalAmount) and minus(TemporalAmount) overloads and the truncatedTo(TemporalUnit) method are also outside the scope of this rule.

How to fix it

Use a supported ChronoUnit for a fixed amount of elapsed time. When an operation must follow calendar rules, convert the Instant to a calendar type such as ZonedDateTime using the intended ZoneId. A custom TemporalUnit is also valid when its implementation explicitly defines the required timeline behavior.

Code examples

Noncompliant code example

import static java.time.temporal.ChronoUnit.YEARS;

void update(Instant instant, Instant end) {
  instant.plus(
    1,
    ChronoUnit.MONTHS); // Noncompliant: "MONTHS" is unsupported by Instant and causes an UnsupportedTemporalTypeException.

  instant.minus(
    1,
    YEARS); // Noncompliant: "YEARS" is unsupported by Instant and causes an UnsupportedTemporalTypeException.

  instant.until(
    end,
    ChronoUnit.WEEKS); // Noncompliant: "WEEKS" is unsupported by Instant and causes an UnsupportedTemporalTypeException.
}

Compliant solution

import static java.time.temporal.ChronoUnit.YEARS;

void update(Instant instant, Instant end, ZoneId zone, TemporalUnit customUnit) {
  // Use supported units for elapsed-time operations.
  instant.plus(1, ChronoUnit.DAYS);
  instant.minus(12, ChronoUnit.HOURS);
  instant.until(end, ChronoUnit.MINUTES);

  // Use a calendar type and an explicit time zone for calendar arithmetic.
  ZonedDateTime dateTime = instant.atZone(zone);
  ZonedDateTime endDateTime = end.atZone(zone);
  dateTime.plus(1, ChronoUnit.MONTHS);
  dateTime.minus(1, YEARS);
  dateTime.until(endDateTime, ChronoUnit.WEEKS);

  // Support for custom units is defined by their implementation.
  instant.plus(1, customUnit);
  instant.minus(1, customUnit);
  instant.until(end, customUnit);
}

Resources

Documentation