Example usage for java.util GregorianCalendar getActualMaximum

List of usage examples for java.util GregorianCalendar getActualMaximum

Introduction

In this page you can find the example usage for java.util GregorianCalendar getActualMaximum.

Prototype

@Override
public int getActualMaximum(int field) 

Source Link

Document

Returns the maximum value that this calendar field could have, taking into consideration the given time value and the current values of the Calendar#getFirstDayOfWeek() getFirstDayOfWeek , Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek , #getGregorianChange() getGregorianChange and Calendar#getTimeZone() getTimeZone methods.

Usage

From source file:Main.java

public static void main(String[] args) {

    GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();

    // get actual maximum for day_of_month
    int max = cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
    System.out.println("Actual Maximum:" + max);

    // get actual maximum for YEAR
    max = cal.getActualMaximum(GregorianCalendar.YEAR);
    System.out.println("Actual Maximum:" + max);

}

From source file:com.saax.gestorweb.util.DAOAleatorio.java

public static Date getDataByOffset(int offsetDataAtual, boolean up) {
    GregorianCalendar gc = new GregorianCalendar();
    Date hoje = DateUtils.truncate(new Date(), Calendar.DATE);
    gc.setTime(hoje); // hoje truncando as horas

    for (int i = 0; i < offsetDataAtual; i++) {
        gc.roll(GregorianCalendar.DAY_OF_MONTH, up);
        if (gc.getActualMaximum(GregorianCalendar.DAY_OF_MONTH) == gc.get(GregorianCalendar.DAY_OF_MONTH)) {
            gc.roll(GregorianCalendar.MONTH, up);

        }//from   w ww  .j a  v a  2 s  .  c o m
    }
    return DateUtils.truncate(new Date(gc.getTimeInMillis()), Calendar.DATE);

}

From source file:DateUtility.java

/**
 * This utility returns the last millsecond 
 * of the month, and year, and timezone supplied as arguments.
 *
 * @param int month/*from   www . j a v  a2s . c  om*/
 * @param int year
 * @param TimeZone tz
 * @return long
 */
static public long getLastMilliOfMonth(int year, int month, TimeZone tz) {
    GregorianCalendar cal = new GregorianCalendar(year, (month - 1), 1);
    cal.setTimeZone(tz);

    // set the maximum last day
    int lastday = cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
    cal.set(GregorianCalendar.DAY_OF_MONTH, lastday);

    // set other calendar maximums.  - we should do this programatically
    // too but i'm too lazy, and i dont think they're gonna change the gregorian
    // calendar anytime soon.. eh?
    cal.set(GregorianCalendar.HOUR_OF_DAY, 23);
    cal.set(GregorianCalendar.MINUTE, 59);
    cal.set(GregorianCalendar.SECOND, 59);
    cal.set(GregorianCalendar.MILLISECOND, 999);

    long time = cal.getTime().getTime();
    return time;
}

From source file:com.strider.datadefender.extensions.BiographicFunctions.java

/**
 * Generates random 9-digit social insurance number
 * @return String//w w w.j a v a  2  s .  c  o  m
 * @throws java.text.ParseException
 */
public java.sql.Date randomBirthDate() throws java.text.ParseException {
    final GregorianCalendar gc = new GregorianCalendar();
    final int year = randBetween(1900, 2016);

    gc.set(GregorianCalendar.YEAR, year);

    final int dayOfYear = randBetween(1, gc.getActualMaximum(GregorianCalendar.DAY_OF_YEAR));

    gc.set(GregorianCalendar.DAY_OF_YEAR, dayOfYear);

    final String birthDate = prependZero(gc.get(GregorianCalendar.DAY_OF_MONTH)) + "-"
            + prependZero(gc.get(GregorianCalendar.MONTH) + 1) + "-" + gc.get(GregorianCalendar.YEAR);

    log.debug("BirthDate:[" + birthDate + "]");

    final DateFormat format = new SimpleDateFormat("dd-MM-yyyy", Locale.US);
    final java.sql.Date date = new java.sql.Date(format.parse(birthDate).getTime());

    log.debug("Generated BirthDate:[" + date.toString() + "]");

    return date;
}

From source file:com.advdb.footballclub.FootBallClub.java

private GregorianCalendar randomYear(int startYear, int endYear) {

    GregorianCalendar gc = new GregorianCalendar();
    int year = randBetween(startYear, endYear);
    gc.set(GregorianCalendar.YEAR, year);
    int dayOfYear = randBetween(1, gc.getActualMaximum(GregorianCalendar.DAY_OF_YEAR));
    gc.set(GregorianCalendar.DAY_OF_YEAR, dayOfYear);
    //        System.out.println(gc.get(GregorianCalendar.YEAR) + "-" + (gc.get(GregorianCalendar.MONTH) + 1) + "-" + gc.get(GregorianCalendar.DAY_OF_MONTH));
    return gc;// w w w. j  av a2s.  c om

}

From source file:clummy.classes.DataHandlingClass.java

/**
 * generate random date of birth//from   ww w.java  2  s .c  om
 * @return 
 */
public String getDateOfBirth() {
    GregorianCalendar gc = new GregorianCalendar();

    int year = randBetween(DataHandlingClass.minMaxDOB[0], DataHandlingClass.minMaxDOB[1] - 1);

    gc.set(gc.YEAR, year);

    int dayOfYear = randBetween(1, gc.getActualMaximum(gc.DAY_OF_YEAR));

    gc.set(gc.DAY_OF_YEAR, dayOfYear);

    int month = gc.get(gc.MONTH);
    if (month == 0)
        month = 1;
    if (dateSeperator.equals(" "))
        dateSeperator = "";
    if (dateFormat.equalsIgnoreCase("DDMMYYYY"))
        return String.format("%02d", gc.get(gc.DAY_OF_MONTH)) + dateSeperator + String.format("%02d", month)
                + dateSeperator + gc.get(gc.YEAR);
    else if (dateFormat.equalsIgnoreCase("MMDDYYYY"))
        return String.format("%02d", month) + dateSeperator + String.format("%02d", gc.get(gc.DAY_OF_MONTH))
                + dateSeperator + gc.get(gc.YEAR);
    else if (dateFormat.equalsIgnoreCase("YYYYDDMM"))
        return gc.get(gc.YEAR) + dateSeperator + String.format("%02d", gc.get(gc.DAY_OF_MONTH)) + dateSeperator
                + String.format("%02d", month);
    else
        return gc.get(gc.YEAR) + dateSeperator + String.format("%02d", month) + dateSeperator
                + String.format("%02d", gc.get(gc.DAY_OF_MONTH));
}

From source file:gr.abiss.calipso.controller.AbstractServiceBasedRestController.java

@RequestMapping(value = "reports", produces = { "application/json" }, method = RequestMethod.GET)
@ResponseBody//  w w w  . j a  v a  2s. c  om
//@ApiOperation(value = "reports", httpMethod = "GET")
public Page<ReportDataSet> getReportDatasets(

        @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
        @RequestParam(value = "size", required = false, defaultValue = "10") Integer size,
        @RequestParam(value = "properties", required = false, defaultValue = "id") String sort,
        @RequestParam(value = "direction", required = false, defaultValue = "ASC") String direction,

        @RequestParam(value = "timeUnit", required = false, defaultValue = "DAY") TimeUnit timeUnit,
        @RequestParam(value = "dateField", required = false, defaultValue = "createdDate") String dateField,
        @RequestParam(value = "period", required = false) String period,
        @RequestParam(value = "reportType", required = false) String reportType) {

    if (StringUtils.isBlank(period)) {
        GregorianCalendar now = new GregorianCalendar();
        StringBuffer buff = new StringBuffer();
        if (timeUnit.equals(TimeUnit.DAY)) {
            buff.append(now.get(Calendar.MONTH)).append('/');
        }
        period = buff.append(now.get(Calendar.YEAR)).toString();
    }
    LOGGER.info("getReportDatasets, timeUnit: " + timeUnit + ", dateField: " + dateField + ", period: " + period
            + ", reportName: " + reportType);
    GregorianCalendar start = null;
    GregorianCalendar end = null;
    if (timeUnit.equals(TimeUnit.DAY)) {
        String[] monthYear = period.split("/");
        start = new GregorianCalendar(Integer.parseInt(monthYear[1]), Integer.parseInt(monthYear[0]) - 1, 0);
        end = new GregorianCalendar(Integer.parseInt(monthYear[1]), Integer.parseInt(monthYear[0]) - 1, 0);
        end.set(Calendar.DAY_OF_MONTH, end.getActualMaximum(Calendar.DAY_OF_MONTH));
    } else {
        start = new GregorianCalendar(Integer.parseInt(period), 0, 0);
        end = new GregorianCalendar(Integer.parseInt(period), 11, 0);
        end.set(Calendar.DAY_OF_MONTH, end.getActualMaximum(Calendar.DAY_OF_MONTH));
    }

    start.set(Calendar.HOUR_OF_DAY, start.getMinimum(Calendar.HOUR_OF_DAY));
    start.set(Calendar.MINUTE, start.getMinimum(Calendar.MINUTE));
    start.set(Calendar.SECOND, start.getMinimum(Calendar.SECOND));
    start.set(Calendar.MILLISECOND, start.getMinimum(Calendar.MILLISECOND));

    end.set(Calendar.HOUR_OF_DAY, end.getMinimum(Calendar.HOUR_OF_DAY));
    end.set(Calendar.MINUTE, end.getMinimum(Calendar.MINUTE));
    end.set(Calendar.SECOND, end.getMinimum(Calendar.SECOND));
    end.set(Calendar.MILLISECOND, end.getMinimum(Calendar.MILLISECOND));

    Map<String, String[]> paramsMap = request.getParameterMap();
    LOGGER.info("getReportDatasets, timeUnit: " + timeUnit + ", dateField: " + dateField + ", dateFrom: "
            + start + ", dateTo: " + end + ", reportName: " + reportType);
    Pageable pageable = buildPageable(page, size, sort, direction, paramsMap);
    Page<ReportDataSet> results = this.service.getReportDatasets(pageable, timeUnit, dateField, start.getTime(),
            end.getTime(), reportType);
    LOGGER.info("getReportDatasets returning " + results.getTotalElements());
    return results;
}

From source file:it.cineca.iris.restclient.main.Command.java

/**
 * Utiliy method//from ww  w . j  a  va2  s .co m
 * 
 * @param min
 * @param max
 * @return random date as string.
 */
private String getRandomDate(int min, int max) {
    GregorianCalendar gc = new GregorianCalendar();
    int year = randBetween(min, max);
    gc.set(gc.YEAR, year);
    int dayOfYear = randBetween(1, gc.getActualMaximum(gc.DAY_OF_YEAR));
    gc.set(gc.DAY_OF_YEAR, dayOfYear);

    SimpleDateFormat fmt = new SimpleDateFormat("dd/MM/yyyy");
    String dateFormatted = fmt.format(gc.getTime());
    System.out.println("Random Date: " + dateFormatted);

    return dateFormatted;
}

From source file:eionet.util.Util.java

/**
 * A method for calculating time difference in MILLISECONDS, between a date-time specified in input parameters and the current
 * date-time. <BR>//  www .j av  a  2 s.c o m
 * This should be useful for calculating sleep time for code that has a certain schedule for execution.
 *
 * @param hour
 *            An integer from 0 to 23. If less than 0 or more than 23, then the closest next hour to current hour is taken.
 * @param date
 *            An integer from 1 to 31. If less than 1 or more than 31, then the closest next date to current date is taken.
 * @param month
 *            An integer from Calendar.JANUARY to Calendar.DECEMBER. If out of those bounds, the closest next month to current
 *            month is taken.
 * @param wday
 *            An integer from 1 to 7. If out of those bounds, the closest next weekday to weekday month is taken.
 * @param zone
 *            A String specifying the time-zone in which the calculations should be done. Please see Java documentation an
 *            allowable time-zones and formats.
 * @return Time difference in milliseconds.
 */
public static long timeDiff(int hour, int date, int month, int wday, String zone) {

    GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone(zone));
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);

    cal.setFirstDayOfWeek(Calendar.MONDAY);

    /*
     * here we force the hour to be one of the defualts if (hour < 0) hour = 0; if (hour > 23) hour = 23;
     */
    int cur_hour = cal.get(Calendar.HOUR);

    if (cal.get(Calendar.AM_PM) == Calendar.PM) {
        cur_hour = 12 + cur_hour;
    }

    // here we assume that every full hour is accepted
    /*
     * if (hour < 0 || hour > 23) { hour = cur_hour>=23 ? 0 : cur_hour + 1; }
     */

    if (wday >= 1 && wday <= 7) {

        int cur_wday = cal.get(Calendar.DAY_OF_WEEK);
        if (hour < 0 || hour > 23) {
            if (cur_wday != wday) {
                hour = 0;
            } else {
                hour = cur_hour >= 23 ? 0 : cur_hour + 1;
            }
        }

        int amount = wday - cur_wday;
        if (amount < 0) {
            amount = 7 + amount;
        }
        if (amount == 0 && cur_hour >= hour) {
            amount = 7;
        }
        cal.add(Calendar.DAY_OF_WEEK, amount);
    } else if (month >= Calendar.JANUARY && month <= Calendar.DECEMBER) { // do something about when every date is accepted
        if (date < 1) {
            date = 1;
        }
        if (date > 31) {
            date = 31;
        }
        int cur_month = cal.get(Calendar.MONTH);
        int amount = month - cur_month;
        if (amount < 0) {
            amount = 12 + amount;
        }
        if (amount == 0) {
            if (cal.get(Calendar.DATE) > date) {
                amount = 12;
            } else if (cal.get(Calendar.DATE) == date) {
                if (cur_hour >= hour) {
                    amount = 12;
                }
            }
        }
        // cal.set(Calendar.DATE, date);
        cal.add(Calendar.MONTH, amount);
        if (date > cal.getActualMaximum(Calendar.DATE)) {
            date = cal.getActualMaximum(Calendar.DATE);
        }
        cal.set(Calendar.DATE, date);
    } else if (date >= 1 && date <= 31) {
        int cur_date = cal.get(Calendar.DATE);
        if (cur_date > date) {
            cal.add(Calendar.MONTH, 1);
        } else if (cur_date == date) {
            if (cur_hour >= hour) {
                cal.add(Calendar.MONTH, 1);
            }
        }
        cal.set(Calendar.DATE, date);
    } else {
        if (hour < 0 || hour > 23) {
            hour = cur_hour >= 23 ? 0 : cur_hour + 1;
        }
        if (cur_hour >= hour) {
            cal.add(Calendar.DATE, 1);
        }
    }

    if (hour >= 12) {
        cal.set(Calendar.HOUR, hour - 12);
        cal.set(Calendar.AM_PM, Calendar.PM);
    } else {
        cal.set(Calendar.HOUR, hour);
        cal.set(Calendar.AM_PM, Calendar.AM);
    }

    Date nextDate = cal.getTime();
    Date currDate = new Date();

    long nextTime = cal.getTime().getTime();
    long currTime = (new Date()).getTime();

    return nextTime - currTime;
}

From source file:com.zimbra.cs.mailbox.calendar.ZRecur.java

public List<Date> expandRecurrenceOverRange(ParsedDateTime dtStart, long rangeStart, long rangeEnd)
        throws ServiceException {
    List<Date> toRet = new LinkedList<Date>();

    Date rangeStartDate = new Date(rangeStart);
    // subtract 1000ms (1sec) because the code in the method treats
    // end time as inclusive while the rangeEnd input argument is
    // exclusive value
    Date rangeEndDate = new Date(rangeEnd - 1000);
    Date dtStartDate = new Date(dtStart.getUtcTime());

    Date earliestDate;//from  www .j  a v  a 2  s. co m
    if (dtStartDate.after(rangeStartDate))
        earliestDate = dtStartDate;
    else
        earliestDate = rangeStartDate;

    if (mUntil != null) {
        Date until = mUntil.getDateForRecurUntil(dtStart.getTimeZone());
        if (until.before(rangeEndDate))
            rangeEndDate = until;
    }

    // Set limit of expansion count.
    int maxInstancesFromConfig = sExpansionLimits.maxInstances;
    int maxInstancesExpanded;
    if (maxInstancesFromConfig <= 0)
        maxInstancesExpanded = mCount;
    else if (mCount <= 0)
        maxInstancesExpanded = maxInstancesFromConfig;
    else
        maxInstancesExpanded = Math.min(mCount, maxInstancesFromConfig);
    int numInstancesExpanded = 1; // initially 1 rather than 0 because DTSTART is always included

    // Set hard limit of expansion time range.  (bug 21989)
    ParsedDateTime earliestDateTime = ParsedDateTime.fromUTCTime(earliestDate.getTime());
    Date hardEndDate = getEstimatedEndTime(earliestDateTime);
    if (hardEndDate.before(rangeEndDate))
        rangeEndDate = hardEndDate;

    if (rangeEndDate.before(earliestDate)) {
        ZimbraLog.calendar.debug(
                "Expanding recurrence over range where range end %s is before earliest date %s",
                DateUtil.formatDate(rangeEndDate), DateUtil.formatDate(earliestDate));
        return toRet;
    }

    GregorianCalendar cur = dtStart.getCalendarCopy();
    int baseMonthDay = cur.get(Calendar.DAY_OF_MONTH);
    boolean baseIsLeapDay = ((baseMonthDay == 29) && (cur.get(Calendar.MONTH) == Calendar.FEBRUARY));

    // until we hit rangeEnd, or we've SAVED count entries:
    //
    //     gather each set {
    //
    //
    //
    //        curDate forward one INTERVAL
    //
    //     }
    //     check Set against BYSETPOS & ranges & count
    //

    int interval = mInterval;
    if (interval <= 0)
        interval = 1;

    // DTSTART is always part of the expansion, as long as it falls within
    // the range.
    if (!dtStartDate.before(earliestDate) && !dtStartDate.after(rangeEndDate))
        toRet.add(dtStartDate);

    int numConsecutiveIterationsWithoutMatchingInstance = 0;
    boolean pastHardEndTime = false;
    long numIterations = 0; // track how many times we looped
    while (!pastHardEndTime && (maxInstancesExpanded <= 0 || numInstancesExpanded < maxInstancesExpanded)) {
        numIterations++;
        boolean curIsAtOrAfterEarliestDate = !cur.getTime().before(earliestDate);
        boolean curIsAfterEndDate = cur.getTime().after(rangeEndDate);
        List<Calendar> addList = new LinkedList<Calendar>();

        switch (mFreq) {
        case HOURLY:
            /*
             * BYSECOND - for each listed second
             * BYMINUTE - for each listed minute in hour
             * BYHOUR - match iff in hour list
             * BYDAY - for each day listed
             * BYMONTHDAY - only those monthdays
             * BYYEARDAY - only those yeardays
             * BYMONTH - only those months
             */
            if (!checkMonthList(cur))
                continue;

            if (!checkYearDayList(cur))
                continue;

            if (!checkMonthDayList(cur))
                continue;

            if (!checkDayList(cur))
                continue;

            if (!checkHourList(cur))
                continue;

            addList.add((Calendar) (cur.clone()));

            cur.add(Calendar.HOUR_OF_DAY, interval);

            addList = expandHourList(addList);
            addList = expandMinuteList(addList);
            addList = expandSecondList(addList);

            break;
        case DAILY:
            /*
             * BYSECOND - for each listed second in day
             * BYMINUTE - for each listed minute in day
             * BYHOUR - for each listed hour in day
             * BYDAY - no ordinal allowed, match iff in day list
             * BYMONTHDAY - only that day
             * BYYEARDAY - only that day
             * BYWEEKNO -- YEARLY ONLY
             * BYMONTH - only that month
             *
             * while (count check & until check & rangeEnd check) {
             *    if (byMonth && !month matches)
             *      curDay = set MONTH to matching month
             *
             *    if (byYearDay && !yearday matches)
             *      curDay = set DAY to next matching yearday
             *
             *    if (byMonthday && !monthday matches)
             *      curDay = skip to next matching monthday
             *
             *    if (byDay && !day in list)
             *      curDay = skip to next mathcing byDay
             *
             *    if (!byHour or FOR EACH HOUR IN HOURLIST)
             *      if (!byMinute or FOR EACH MINUTE IN MINLIST)
             *        if (!bySecond or FOR EACH SECOND IN LIST)
             *          ----add to list---
             *
             *     check against BYSETPOS
             *
             *     curDay+=1 day
             * }
             *
             */

            if (!checkMonthList(cur))
                continue;

            if (!checkYearDayList(cur))
                continue;

            if (!checkMonthDayList(cur))
                continue;

            if (!checkDayList(cur))
                continue;

            addList.add((Calendar) (cur.clone()));

            cur.add(Calendar.DAY_OF_YEAR, interval);

            addList = expandHourList(addList);
            addList = expandMinuteList(addList);
            addList = expandSecondList(addList);
            break;
        case WEEKLY:
            /*
             * BYSECOND - for every listed second
             * BYMINUTE - for every listed minute
             * BYHOUR - for every listed hour
             * BYDAY - for every listed day
             * BYMONTHDAY - MAYBE once a month
             * BYYEARDAY - MAYBE once a year
             * BYMONTH - iff month matches
             *
             *  for each (INTERVAL)WEEK{
             *    if (byMonth && !month matches)
             *      curDay = set MONTH to DtStart in next matching month
             *
             *    if (byYearDay && !yearday matches)
             *      curDay = set date to next matching yearday
             *
             *    if (byMonthDay && !monthday matches)
             *      curDay = skip to next matching monthday
             *
             *    if (!byDay or FOREACH day in list)
             *      if (!byHour or FOREACH hour in list)
             *        if (!byMinute or FOREACH minute in list)
             *          if (!bySecond or FOREACH second in list)
             *            ----add to list----
             *
             *    check against BYSETPOS
             *
             *    curDay += 1 week
             * } while (count check & until check & rangeEnd check)
             *
             */
            if (!checkMonthList(cur))
                continue;

            if (!checkYearDayList(cur))
                continue;

            if (!checkMonthDayList(cur))
                continue;

            addList.add((Calendar) (cur.clone()));

            cur.add(Calendar.WEEK_OF_YEAR, interval);

            addList = expandDayListForWeekly(addList);
            addList = expandHourList(addList);
            addList = expandMinuteList(addList);
            addList = expandSecondList(addList);
            break;
        case MONTHLY:
            if (!checkMonthList(cur))
                continue;

            if (!checkYearDayList(cur))
                continue;

            addList.add((Calendar) (cur.clone()));

            cur.set(Calendar.DAY_OF_MONTH, 1);
            cur.add(Calendar.MONTH, interval);
            int daysInMonth = cur.getActualMaximum(Calendar.DAY_OF_MONTH);
            cur.set(Calendar.DAY_OF_MONTH, Math.min(baseMonthDay, daysInMonth));

            addList = expandMonthDayList(addList);
            addList = expandDayListForMonthlyYearly(addList);
            addList = expandHourList(addList);
            addList = expandMinuteList(addList);
            addList = expandSecondList(addList);

            break;
        case YEARLY:
            /*
             * BYSECOND
             * BYMINUTE
             * BYHOUR
             * BYDAY
             * BYMONTHDAY
             * BYYEARDAY
             * BYWEEKNO - specified week
             * BYMONTH - once
             */
            if (baseIsLeapDay) {
                // previously adding a year to a leap day will have rounded down to the 28th.
                // If this happened, we need to be sure that if we are back in a leap
                // year, it is back at 29th
                cur.set(Calendar.DAY_OF_MONTH, cur.getActualMaximum(Calendar.DAY_OF_MONTH));
            }
            if (ignoreYearForRecurrenceExpansion(cur, baseIsLeapDay)) {
                cur.add(Calendar.YEAR, interval);
                break;
            }
            addList.add((Calendar) (cur.clone()));

            cur.add(Calendar.YEAR, interval);

            addList = expandMonthList(addList);
            addList = expandYearDayList(addList);

            addList = expandMonthDayList(addList);
            addList = expandDayListForMonthlyYearly(addList);
            addList = expandHourList(addList);
            addList = expandMinuteList(addList);
            addList = expandSecondList(addList);

            break;
        default:
            // MINUTELY and SECONDLY are intentionally not supported for performance reasons.
            return toRet;
        }

        addList = handleSetPos(addList);

        boolean noInstanceFound = true;
        boolean foundInstancePastEndDate = false;
        // add all the ones that match!
        for (Calendar addCal : addList) {
            Date toAdd = addCal.getTime();

            // We already counted DTSTART before the main loop, so don't
            // count it twice.
            if (toAdd.compareTo(dtStartDate) == 0) {
                noInstanceFound = false;
                continue;
            }

            // we still have expanded this instance, even if it isn't in our
            // current date window
            if (toAdd.after(dtStartDate))
                numInstancesExpanded++;

            if (!toAdd.after(rangeEndDate)) {
                if (!toAdd.before(earliestDate)) {
                    toRet.add(toAdd);
                    noInstanceFound = false;
                }
            } else {
                foundInstancePastEndDate = true;
                break;
            }

            if (maxInstancesExpanded > 0 && numInstancesExpanded >= maxInstancesExpanded)
                break;
        }

        // Detect invalid rule.  If the rule was invalid the current iteration, which is for the current
        // frequency interval, would have found no matching instance.  The next iteration will also find
        // no matching instance, and there is no need to keep iterating until we go past the hard end
        // time or COUNT/UNTIL limit.
        //
        // However, we have to make an exception for leap year.  An yearly rule looking for February 29th
        // will find no instance in up to 3 consecutive years before finding Feb 29th in the fourth year.
        //
        // So the invalid rule detection must look for at least 4 consecutive failed iterations.
        if (curIsAtOrAfterEarliestDate) {
            if (noInstanceFound)
                numConsecutiveIterationsWithoutMatchingInstance++;
            else
                numConsecutiveIterationsWithoutMatchingInstance = 0;
            if (numConsecutiveIterationsWithoutMatchingInstance >= 4) {
                ZimbraLog.calendar.warn("Invalid recurrence rule: " + toString());
                return toRet;
            }
        }

        pastHardEndTime = foundInstancePastEndDate || (noInstanceFound && curIsAfterEndDate);
    }

    return toRet;
}