Example #1
0
 /**
  * Add a date to the list. The date will be updated to reflect the timezone of this list.
  *
  * @param date the date to add
  * @return true
  * @see List#add(java.lang.Object)
  */
 public final boolean add(final Date date) {
   if (date instanceof DateTime) {
     if (isUtc()) {
       ((DateTime) date).setUtc(true);
     } else {
       ((DateTime) date).setTimeZone(getTimeZone());
     }
   } else if (!Value.DATE.equals(getType())) {
     DateTime dateTime = new DateTime(date);
     dateTime.setTimeZone(getTimeZone());
     return add((Object) dateTime);
   }
   return add((Object) date);
 }
Example #2
0
 /**
  * Constructs a new instance from the specified string value.
  *
  * @param aValue a string representation of a recurrence.
  * @throws ParseException thrown when the specified string contains an invalid representation of
  *     an UNTIL date value
  */
 public Recur(final String aValue) throws ParseException {
   final StringTokenizer t = new StringTokenizer(aValue, ";=");
   while (t.hasMoreTokens()) {
     final String token = t.nextToken();
     if (FREQ.equals(token)) {
       frequency = nextToken(t, token);
     } else if (UNTIL.equals(token)) {
       final String untilString = nextToken(t, token);
       if (untilString != null && untilString.indexOf("T") >= 0) {
         until = new DateTime(untilString);
         // UNTIL must be specified in UTC time..
         ((DateTime) until).setUtc(true);
       } else {
         until = new Date(untilString);
       }
     } else if (COUNT.equals(token)) {
       count = Integer.parseInt(nextToken(t, token));
     } else if (INTERVAL.equals(token)) {
       interval = Integer.parseInt(nextToken(t, token));
     } else if (BYSECOND.equals(token)) {
       secondList = new NumberList(nextToken(t, token), 0, 59, false);
     } else if (BYMINUTE.equals(token)) {
       minuteList = new NumberList(nextToken(t, token), 0, 59, false);
     } else if (BYHOUR.equals(token)) {
       hourList = new NumberList(nextToken(t, token), 0, 23, false);
     } else if (BYDAY.equals(token)) {
       dayList = new WeekDayList(nextToken(t, token));
     } else if (BYMONTHDAY.equals(token)) {
       monthDayList = new NumberList(nextToken(t, token), 1, 31, true);
     } else if (BYYEARDAY.equals(token)) {
       yearDayList = new NumberList(nextToken(t, token), 1, 366, true);
     } else if (BYWEEKNO.equals(token)) {
       weekNoList = new NumberList(nextToken(t, token), 1, 53, true);
     } else if (BYMONTH.equals(token)) {
       monthList = new NumberList(nextToken(t, token), 1, 12, false);
     } else if (BYSETPOS.equals(token)) {
       setPosList = new NumberList(nextToken(t, token), 1, 366, true);
     } else if (WKST.equals(token)) {
       weekStartDay = nextToken(t, token);
     }
     // assume experimental value..
     else {
       experimentalValues.put(token, nextToken(t, token));
     }
   }
   validateFrequency();
 }
Example #3
0
  /**
   * Returns the the next date of this recurrence given a seed date and start date. The seed date
   * indicates the start of the fist occurrence of this recurrence. The start date is the starting
   * date to search for the next recurrence. Return null if there is no occurrence date after start
   * date.
   *
   * @return the next date in the recurrence series after startDate
   * @param seed the start date of this Recurrence's first instance
   * @param startDate the date to start the search
   */
  public final Date getNextDate(final Date seed, final Date startDate) {

    final Calendar cal = Dates.getCalendarInstance(seed);
    cal.setTime(seed);

    // optimize the start time for selecting candidates
    // (only applicable where a COUNT is not specified)
    if (getCount() < 1) {
      final Calendar seededCal = (Calendar) cal.clone();
      while (seededCal.getTime().before(startDate)) {
        cal.setTime(seededCal.getTime());
        increment(seededCal);
      }
    }

    int invalidCandidateCount = 0;
    int noCandidateIncrementCount = 0;
    Date candidate = null;
    final Value value = seed instanceof DateTime ? Value.DATE_TIME : Value.DATE;

    while (true) {
      final Date candidateSeed = Dates.getInstance(cal.getTime(), value);

      if (getUntil() != null && candidate != null && candidate.after(getUntil())) {
        break;
      }

      if (getCount() > 0 && invalidCandidateCount >= getCount()) {
        break;
      }

      if (Value.DATE_TIME.equals(value)) {
        if (((DateTime) seed).isUtc()) {
          ((DateTime) candidateSeed).setUtc(true);
        } else {
          ((DateTime) candidateSeed).setTimeZone(((DateTime) seed).getTimeZone());
        }
      }

      final DateList candidates = getCandidates(candidateSeed, value);
      if (!candidates.isEmpty()) {
        noCandidateIncrementCount = 0;
        // sort candidates for identifying when UNTIL date is exceeded..
        Collections.sort(candidates);

        for (final Iterator<Date> i = candidates.iterator(); i.hasNext(); ) {
          candidate = i.next();
          // don't count candidates that occur before the seed date..
          if (!candidate.before(seed)) {
            // Candidate must be after startDate because
            // we want the NEXT occurrence
            if (!candidate.after(startDate)) {
              invalidCandidateCount++;
            } else if (getCount() > 0 && invalidCandidateCount >= getCount()) {
              break;
            } else if (!(getUntil() != null && candidate.after(getUntil()))) {
              return candidate;
            }
          }
        }
      } else {
        noCandidateIncrementCount++;
        if ((maxIncrementCount > 0) && (noCandidateIncrementCount > maxIncrementCount)) {
          break;
        }
      }
      increment(cal);
    }
    return null;
  }
Example #4
0
  /**
   * Returns a list of start dates in the specified period represented by this recur. This method
   * includes a base date argument, which indicates the start of the fist occurrence of this
   * recurrence. The base date is used to inject default values to return a set of dates in the
   * correct format. For example, if the search start date (start) is Wed, Mar 23, 12:19PM, but the
   * recurrence is Mon - Fri, 9:00AM - 5:00PM, the start dates returned should all be at 9:00AM, and
   * not 12:19PM.
   *
   * @return a list of dates represented by this recur instance
   * @param seed the start date of this Recurrence's first instance
   * @param periodStart the start of the period
   * @param periodEnd the end of the period
   * @param value the type of dates to generate (i.e. date/date-time)
   * @param maxCount limits the number of instances returned. Up to one years worth extra may be
   *     returned. Less than 0 means no limit
   */
  public final DateList getDates(
      final Date seed,
      final Date periodStart,
      final Date periodEnd,
      final Value value,
      final int maxCount) {

    final DateList dates = new DateList(value);
    if (seed instanceof DateTime) {
      if (((DateTime) seed).isUtc()) {
        dates.setUtc(true);
      } else {
        dates.setTimeZone(((DateTime) seed).getTimeZone());
      }
    }
    final Calendar cal = Dates.getCalendarInstance(seed);
    cal.setTime(seed);

    // optimize the start time for selecting candidates
    // (only applicable where a COUNT is not specified)
    if (getCount() < 1) {
      final Calendar seededCal = (Calendar) cal.clone();
      while (seededCal.getTime().before(periodStart)) {
        cal.setTime(seededCal.getTime());
        increment(seededCal);
      }
    }

    int invalidCandidateCount = 0;
    int noCandidateIncrementCount = 0;
    Date candidate = null;
    while ((maxCount < 0) || (dates.size() < maxCount)) {
      final Date candidateSeed = Dates.getInstance(cal.getTime(), value);

      if (getUntil() != null && candidate != null && candidate.after(getUntil())) {

        break;
      }
      if (periodEnd != null && candidate != null && candidate.after(periodEnd)) {

        break;
      }
      if (getCount() >= 1 && (dates.size() + invalidCandidateCount) >= getCount()) {

        break;
      }

      //            if (Value.DATE_TIME.equals(value)) {
      if (candidateSeed instanceof DateTime) {
        if (dates.isUtc()) {
          ((DateTime) candidateSeed).setUtc(true);
        } else {
          ((DateTime) candidateSeed).setTimeZone(dates.getTimeZone());
        }
      }

      final DateList candidates = getCandidates(candidateSeed, value);
      if (!candidates.isEmpty()) {
        noCandidateIncrementCount = 0;
        // sort candidates for identifying when UNTIL date is exceeded..
        Collections.sort(candidates);
        for (final Iterator<Date> i = candidates.iterator(); i.hasNext(); ) {
          candidate = i.next();
          // don't count candidates that occur before the seed date..
          if (!candidate.before(seed)) {
            // candidates exclusive of periodEnd..
            if (candidate.before(periodStart) || !candidate.before(periodEnd)) {
              invalidCandidateCount++;
            } else if (getCount() >= 1 && (dates.size() + invalidCandidateCount) >= getCount()) {
              break;
            } else if (!(getUntil() != null && candidate.after(getUntil()))) {
              dates.add(candidate);
            }
          }
        }
      } else {
        noCandidateIncrementCount++;
        if ((maxIncrementCount > 0) && (noCandidateIncrementCount > maxIncrementCount)) {
          break;
        }
      }
      increment(cal);
    }
    // sort final list..
    Collections.sort(dates);
    return dates;
  }