private TimeRange getRightmostTimeRange() {
    long retStartTime;
    long retEndTime;
    long queryRange = endTime - startTime;
    long intervalNum;

    if (slidingStep.containsMonth()) {
      intervalNum =
          (long)
              Math.ceil(
                  (double) queryRange
                      / (slidingStep.getMaxTotalDuration(TimestampPrecisionUtils.currPrecision)));
      long tempRetStartTime =
          DateTimeUtils.calcPositiveIntervalByMonth(
              startTime, slidingStep.multiple(intervalNum - 1), zoneId);
      retStartTime = tempRetStartTime;
      while (tempRetStartTime < endTime) {
        intervalNum++;
        retStartTime = tempRetStartTime;
        tempRetStartTime =
            DateTimeUtils.calcPositiveIntervalByMonth(
                retStartTime, slidingStep.multiple(intervalNum - 1), zoneId);
      }
      intervalNum -= 1;
    } else {
      intervalNum = (long) Math.ceil(queryRange / (double) slidingStep.nonMonthDuration);
      retStartTime = slidingStep.nonMonthDuration * (intervalNum - 1) + startTime;
    }

    if (interval.containsMonth()) {
      // calculate interval length by natural month based on curStartTime
      // ie. startTIme = 1/31, interval = 1mo, curEndTime will be set to 2/29
      retEndTime =
          Math.min(
              DateTimeUtils.calcPositiveIntervalByMonth(
                  startTime, interval.merge(slidingStep.multiple(intervalNum - 1)), zoneId),
              endTime);
    } else {
      retEndTime = Math.min(retStartTime + interval.nonMonthDuration, endTime);
    }
    return new TimeRange(retStartTime, retEndTime);
  }
This class iteratively generates aggregated time windows.

<p>For example, startTime = 0, endTime = 10, interval = 5, slidingStep = 3, leftCloseRightOpen,
return [0,5],[3,7],[6,9],[9,9]
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/aggregation/timerangeiterator/AggrWindowIterator.java