material-components/material-components-android · error · IllegalArgumentException

Only Gregorian calendars are supported.

Error message

Only Gregorian calendars are supported.

What it means

Month.monthsUntil computes month distance arithmetically and only works when the underlying Calendar is a GregorianCalendar (the arithmetic year*12+month is Gregorian-specific). If firstOfMonth is any other Calendar implementation, it throws IllegalArgumentException stating only Gregorian calendars are supported.

Source

Thrown at lib/java/com/google/android/material/datepicker/Month.java:151

  @Override
  public int compareTo(@NonNull Month other) {
    return firstOfMonth.compareTo(other.firstOfMonth);
  }

  /**
   * Returns the number of months from this Month to the provided Month.
   *
   * <p>0 when {@code this.compareTo(other)} is 0. Negative when {@code this.compareTo(other)} is
   * negative.
   *
   * @throws IllegalArgumentException when {@link Calendar#getInstance()} is not an instance of
   *     {@link GregorianCalendar}
   */
  int monthsUntil(@NonNull Month other) {
    if (firstOfMonth instanceof GregorianCalendar) {
      return (other.year - year) * 12 + (other.month - month);
    } else {
      throw new IllegalArgumentException("Only Gregorian calendars are supported.");
    }
  }

  long getStableId() {
    return firstOfMonth.getTimeInMillis();
  }

  /**
   * Gets a long for the specific day within the instance's month and year.
   *
   * <p>This method only guarantees validity with respect to {@link Calendar#isLenient()}.
   *
   * @param day The desired day within this month and year
   * @return A long representing a time in milliseconds for the given day within the specified month
   *     and year
   */
  long getDay(int day) {
    Calendar dayCalendar = UtcDates.getDayCopy(firstOfMonth);

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Switch the affected calendar usage to a Gregorian locale: Calendar.getInstance(TimeZone.UTC, Locale.US) — the same policy UtcDates uses.
  2. Change the device/emulator calendar setting to Gregorian if it is set to another calendar system.
  3. Update Material Components; verify you are not constructing Month from a custom Calendar subclass.

Example fix

// before
val cal = Calendar.getInstance(localeWithNonGregorianCalendar)
val month = Month.create(cal) // monthsUntil() later throws

// after
val cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US)
val month = Month.create(cal)
Defensive patterns

Strategy: fallback

Validate before calling

fun isGregorian(calendar: Calendar): Boolean = calendar is GregorianCalendar

val cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US) // guaranteed Gregorian
val month = Month.create(cal)

Type guard

fun supportsMonthArithmetic(cal: Calendar): Boolean = cal is GregorianCalendar

Try / catch

try { month.monthsUntil(other) } catch (e: IllegalArgumentException) { fall back to computing month distance from raw year/month fields, which is calendar-system-specific }

Prevention

When it happens

Trigger: The device/emulator default Calendar.getInstance() returning a non-Gregorian calendar (e.g. an ICU/islamic calendar on certain locales or OEM builds, or a custom Calendar subclass injected into the locale); constructing Month objects from calendars obtained outside UtcDates.

Common situations: Devices or emulators with non-Gregorian calendar locales; forked/OEM system images; code that builds Month.create from a Calendar obtained with Calendar.getInstance(nonGregorianLocale). In stock Material, months are created via UtcDates (UTC/US locale), so users normally only see this via locale-dependent entry points.

Related errors


AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14). Data as JSON: /api/errors/1e5b3133422149ea. Report an issue: GitHub.