YunaiV/yudao-cloud · error · IllegalArgumentException

Invalid interval: {}

Error message

Invalid interval: {}

What it means

LocalDateTimeUtils.addTimeRange loops over an interval enum splitting a time span into day/week/month/quarter/year buckets. The switch's default branch throws IllegalArgumentException for any enum constant outside those five — this is a coding/extension error, not a data error.

Source

Thrown at yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java:338

            case QUARTER:
                while (startTime.isBefore(endTime)) {
                    int quarterOfYear = getQuarterOfYear(startTime);
                    LocalDateTime quarterEnd = quarterOfYear == 4
                            ? startTime.with(TemporalAdjusters.lastDayOfYear()).plusDays(1).minusNanos(1)
                            : startTime.withMonth(quarterOfYear * 3 + 1).withDayOfMonth(1).minusNanos(1);
                    timeRanges.add(new LocalDateTime[]{startTime, quarterEnd});
                    startTime = quarterEnd.plusNanos(1);
                }
                break;
            case YEAR:
                while (startTime.isBefore(endTime)) {
                    LocalDateTime endOfYear = startTime.with(TemporalAdjusters.lastDayOfYear()).plusDays(1).minusNanos(1);
                    timeRanges.add(new LocalDateTime[]{startTime, endOfYear});
                    startTime = endOfYear.plusNanos(1);
                }
                break;
            default:
                throw new IllegalArgumentException("Invalid interval: " + interval);
        }
        // 3. 兜底,最后一个时间,需要保持在 endTime 之前
        LocalDateTime[] lastTimeRange = CollUtil.getLast(timeRanges);
        if (lastTimeRange != null) {
            lastTimeRange[1] = endTime;
        }
        return timeRanges;
    }

    /**
     * 获取从开始日期起的日期列表
     *
     * @param startDate 开始日期
     * @param days 天数
     * @return 日期列表,包含开始日期
     */
    public static List<LocalDate> getDateList(LocalDate startDate, int days) {
        List<LocalDate> dateList = new ArrayList<>(days);

View on GitHub (pinned to 477be9dd49)

Solutions

  1. Pass only DAY, WEEK, MONTH, QUARTER or YEAR to this method.
  2. If a coarser/finer bucket is needed, add an explicit case instead of reusing an unhandled constant.
  3. Convert before calling: e.g. aggregate HOUR data upstream and call with DAY.
  4. Add a unit test enumerating all enum constants against this method so new constants fail the build, not production.

Example fix

// before
List<LocalDateTime[]> ranges = LocalDateTimeUtils.addTimeRange(start, end, IntervalEnum.HOUR);

// after
List<LocalDateTime[]> ranges = LocalDateTimeUtils.addTimeRange(start, end, IntervalEnum.DAY);
Defensive patterns

Strategy: type-guard

Validate before calling

Set<IntervalEnum> supported = EnumSet.of(DAY, WEEK, MONTH, QUARTER, YEAR);
if (!supported.contains(interval)) throw new IllegalArgumentException("Unsupported interval: " + interval);

Type guard

static boolean isSupportedInterval(IntervalEnum i) {
    return i == IntervalEnum.DAY || i == IntervalEnum.WEEK || i == IntervalEnum.MONTH
        || i == IntervalEnum.QUARTER || i == IntervalEnum.YEAR;
}

Prevention

When it happens

Trigger: Calling the method with an interval enum value such as HOUR or MINUTE (present in many interval enums but not handled here), or after someone adds a new constant (e.g. HALF_YEAR) to the enum without extending the switch.

Common situations: Reusing a generic TimeIntervalEnum across features where chart aggregation only supports day..year; adding enum constants in a PR without touching this utility; copy-pasting the util for a new report and passing an unsupported granularity.

Related errors


AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14). Data as JSON: /api/errors/ccec7c9371a3e1a4. Report an issue: GitHub.