Search in sources :

Example 36 with ParsedDateTime

use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.

the class CompleteTaskInstance method createCompletedInstanceInvite.

private Invite createCompletedInstanceInvite(Invite recur, ParsedDateTime dtStart) throws ServiceException {
    Invite inst = new Invite(MailItem.Type.TASK, recur.getMethod(), (recur.getTimeZoneMap() != null) ? recur.getTimeZoneMap().clone() : null, recur.isOrganizer());
    long now = System.currentTimeMillis();
    // Assign a new UID.
    String uid = LdapUtil.generateUUID();
    inst.setUid(uid);
    inst.setSeqNo(0);
    // Set completed status/pct/time.
    inst.setStatus(IcalXmlStrMap.STATUS_COMPLETED);
    inst.setPercentComplete("100");
    inst.setCompleted(now);
    // Set time fields.
    inst.setDtStart(dtStart);
    ParsedDuration dur = recur.getEffectiveDuration();
    if (dur != null) {
        ParsedDateTime due = dtStart.add(dur);
        inst.setDtEnd(due);
    }
    inst.setDtStamp(now);
    // Recurrence-related fields should be unset.
    inst.setRecurrence(null);
    inst.setRecurId(null);
    // Copy the rest of the fields.
    inst.setPriority(recur.getPriority());
    inst.setOrganizer(recur.getOrganizer());
    List<ZAttendee> attendees = recur.getAttendees();
    for (ZAttendee at : attendees) inst.addAttendee(at);
    inst.setName(recur.getName());
    inst.setLocation(recur.getLocation());
    inst.setFlags(recur.getFlags());
    inst.setDescription(recur.getDescription(), recur.getDescriptionHtml());
    inst.setFragment(recur.getFragment());
    return inst;
}
Also used : ParsedDuration(com.zimbra.common.calendar.ParsedDuration) ZAttendee(com.zimbra.cs.mailbox.calendar.ZAttendee) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 37 with ParsedDateTime

use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.

the class CalSummaryCache method reloadCalendarItemOverRange.

// mSummaryCache
//
// key = "accountId:folderId"
// value = CalendarData type
//
// CalendarData = {
//   folderId, range start, range end,
//   // list of CalendarItemData objects (one for each appointment in range)
//   [
//     CalendarItemData {
//       calItemId, folderId, flags, tags, item type,
//       last modified,
//       actual range start, actual range end,
//       uid, isRecurring, isPublic, alarm,
//       default instance data (FullInstanceData type),
//       // list of instances (FullInstanceData if an exception, InstanceData if not)
//       [
//         InstanceData/FullInstanceData, ...
//       ]
//     },
//     CalendarItemData, ...
//   ]
public static CalendarItemData reloadCalendarItemOverRange(CalendarItem calItem, long rangeStart, long rangeEnd) throws ServiceException {
    CalendarItemData calItemData = null;
    try {
        boolean rangeValid = (rangeStart >= CalendarUtils.MICROSOFT_EPOC_START_MS_SINCE_EPOC && rangeEnd > CalendarUtils.MICROSOFT_EPOC_START_MS_SINCE_EPOC && rangeStart < rangeEnd);
        if (!rangeValid) {
            return null;
        }
        Invite defaultInvite = calItem.getDefaultInviteOrNull();
        if (defaultInvite == null) {
            ZimbraLog.calendar.info("Could not load defaultinfo for calendar item with id=" + calItem.getId() + "; SKIPPING");
            return null;
        }
        String defaultFba = null;
        if (calItem instanceof Appointment)
            defaultFba = ((Appointment) calItem).getEffectiveFreeBusyActual(defaultInvite, null);
        AlarmData alarm = null;
        CalendarItem.AlarmData calItemAlarmData = calItem.getAlarmData();
        long alarmTime = 0;
        long alarmInst = 0;
        if (calItemAlarmData != null) {
            alarmTime = calItemAlarmData.getNextAt();
            alarmInst = calItemAlarmData.getNextInstanceStart();
            int alarmInvId = calItemAlarmData.getInvId();
            int alarmCompNum = calItemAlarmData.getCompNum();
            String summary = null, location = null;
            Invite alarmInv = calItem.getInvite(alarmInvId, alarmCompNum);
            if (alarmInv != null) {
                summary = alarmInv.getName();
                location = alarmInv.getLocation();
            }
            alarm = new AlarmData(calItemAlarmData.getNextAt(), calItemAlarmData.getNextInstanceStart(), alarmInvId, alarmCompNum, summary, location, calItemAlarmData.getAlarm());
        }
        Long defDtStartLong = null;
        Long defDurationLong = null;
        ParsedDateTime defDtStart = defaultInvite.getStartTime();
        if (defDtStart != null) {
            defDtStartLong = Long.valueOf(defDtStart.getUtcTime());
            ParsedDateTime defDtEnd = defaultInvite.getEffectiveEndTime();
            if (defDtEnd != null)
                defDurationLong = Long.valueOf(defDtEnd.getUtcTime() - defDtStartLong.longValue());
        }
        String defaultEffectivePartStat = calItem.getEffectivePartStat(defaultInvite, null);
        FullInstanceData defaultData = new FullInstanceData(defaultInvite, null, defDtStartLong, defDurationLong, defaultEffectivePartStat, defaultFba, null);
        calItemData = new CalendarItemData(calItem.getType(), calItem.getFolderId(), calItem.getId(), calItem.getFlagString(), calItem.getTags(), TagUtil.getTagIdString(calItem), calItem.getModifiedSequence(), calItem.getSavedSequence(), calItem.getDate(), calItem.getChangeDate(), calItem.getSize(), defaultInvite.getUid(), defaultInvite.isRecurrence(), calItem.hasExceptions(), calItem.isPublic(), alarm, defaultData);
        long actualRangeStart = 0;
        long actualRangeEnd = 0;
        int numInstances = 0;
        Collection<CalendarItem.Instance> instances = calItem.expandInstances(rangeStart, rangeEnd, true);
        for (CalendarItem.Instance inst : instances) {
            try {
                long instStart = inst.getStart();
                long duration = inst.getEnd() - instStart;
                // 0 means "no DTSTART", however, note that negative numbers are valid
                Long instStartLong = instStart != 0 ? Long.valueOf(instStart) : null;
                Long durationLong = duration > 0 ? Long.valueOf(duration) : null;
                // For an instance whose alarm time is within the time range, we must
                // include it even if its start time is after the range.
                long startOrAlarm = instStart == alarmInst ? alarmTime : instStart;
                boolean hasTimes = inst.hasStart() && inst.hasEnd();
                if (hasTimes && (startOrAlarm >= rangeEnd || inst.getEnd() <= rangeStart)) {
                    continue;
                }
                numInstances++;
                if (hasTimes) {
                    if (actualRangeStart == 0 || startOrAlarm < actualRangeStart)
                        actualRangeStart = startOrAlarm;
                    if (inst.getEnd() > actualRangeEnd)
                        actualRangeEnd = inst.getEnd();
                }
                InviteInfo invId = inst.getInviteInfo();
                Invite inv = calItem.getInvite(invId.getMsgId(), invId.getComponentId());
                Long alarmAt = instStart == alarmInst ? Long.valueOf(alarmTime) : null;
                String fba = inv.getFreeBusyActual();
                if (calItem instanceof Appointment)
                    fba = ((Appointment) calItem).getEffectiveFreeBusyActual(inv, inst);
                String effectivePartStat = calItem.getEffectivePartStat(inv, inst);
                InstanceData instData;
                if (!inst.isException()) {
                    String ridZ = inst.getRecurIdZ();
                    Long tzOffset = instStartLong != null && inst.isAllDay() ? Long.valueOf(inst.getStartTzOffset()) : null;
                    instData = new InstanceData(ridZ, instStartLong, durationLong, alarmAt, tzOffset, effectivePartStat, fba, inv.getPercentComplete(), defaultData);
                } else {
                    String ridZ = null;
                    if (inv.hasRecurId())
                        ridZ = inv.getRecurId().getDtZ();
                    instData = new FullInstanceData(inv, ridZ, instStartLong, durationLong, effectivePartStat, fba, alarmAt);
                }
                calItemData.addInstance(instData);
            } catch (MailServiceException.NoSuchItemException e) {
                ZimbraLog.calendar.info("Error could not get instance " + inst.getMailItemId() + "-" + inst.getComponentNum() + " for appt " + calItem.getId(), e);
            }
        }
        if (numInstances < 1)
            return null;
        calItemData.setActualRange(actualRangeStart, actualRangeEnd);
    } catch (MailServiceException.NoSuchItemException e) {
        ZimbraLog.calendar.info("Error could not get default invite for calendar item: " + calItem.getId(), e);
    } catch (RuntimeException e) {
        ZimbraLog.calendar.info("Caught Exception " + e + " while getting summary info for calendar item: " + calItem.getId(), e);
    }
    return calItemData;
}
Also used : Appointment(com.zimbra.cs.mailbox.Appointment) InviteInfo(com.zimbra.cs.mailbox.calendar.InviteInfo) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 38 with ParsedDateTime

use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.

the class ZRecur method expandRecurrenceOverRange.

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;
    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);
    // initially 1 rather than 0 because DTSTART is always included
    int numInstancesExpanded = 1;
    // 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;
    // the range.
    if (!dtStartDate.before(earliestDate) && !dtStartDate.after(rangeEndDate))
        toRet.add(dtStartDate);
    int numConsecutiveIterationsWithoutMatchingInstance = 0;
    boolean pastHardEndTime = false;
    // track how many times we looped
    long numIterations = 0;
    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:
                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();
            // count it twice.
            if (toAdd.compareTo(dtStartDate) == 0) {
                noInstanceFound = false;
                continue;
            }
            // 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;
        }
        // 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;
}
Also used : GregorianCalendar(java.util.GregorianCalendar) Calendar(java.util.Calendar) GregorianCalendar(java.util.GregorianCalendar) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) LinkedList(java.util.LinkedList) Date(java.util.Date)

Example 39 with ParsedDateTime

use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.

the class ZRecur method main.

public static void main(String[] args) {
    ICalTimeZone tzUTC = ICalTimeZone.getUTC();
    TimeZoneMap tzmap = new TimeZoneMap(tzUTC);
    ParsedDateTime dtStart = null;
    try {
        dtStart = ParsedDateTime.parse("20050101T123456", tzmap, tzUTC, tzUTC);
    } catch (ParseException e) {
        System.out.println("Caught ParseException at start: " + e);
    }
    Date rangeStart;
    Date rangeEnd;
    GregorianCalendar cal = new GregorianCalendar();
    cal.clear();
    cal.setTimeZone(tzUTC);
    cal.set(2005, 4, 15, 0, 0, 0);
    rangeStart = cal.getTime();
    cal.set(2006, 0, 1, 0, 0, 0);
    rangeEnd = cal.getTime();
    try {
        ZRecur test = new ZRecur("FREQ=DAILY;BYMONTH=5,6", tzmap);
        System.out.println("\n\n" + test.toString() + "\n-------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            cal.setTimeZone(tzUTC);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=DAILY;BYMONTH=5,6;BYDAY=TH,-1MO", tzmap);
        System.out.println("\n\n" + test.toString() + "\n-------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            cal.setTimeZone(tzUTC);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=DAILY;BYMONTH=5,6;BYMONTHDAY=1,3,5,7,9,31", tzmap);
        System.out.println("\n\n" + test.toString() + "\n-------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=DAILY;BYMONTH=5,6;BYMONTHDAY=1,3,5,7,9,31;BYDAY=SU,SA", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=DAILY;BYMONTH=5,6;BYMONTHDAY=1,3,5,7,9,31;BYDAY=SU,SA;BYHOUR=21,0", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=DAILY;BYMONTH=5,6;BYMONTHDAY=1,3,5,7,9,31;BYDAY=SU;BYHOUR=21,0;BYMINUTE=23", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=DAILY;BYMONTH=5,6;BYMONTHDAY=1,3,5,7,9,31;BYDAY=SU;BYHOUR=1,21,0;BYSECOND=0,59", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        // parse error testing
        ZRecur test = new ZRecur("FREQ=DAILY;BIYMONTH=5,6;BYMONTHDAY=1,3,5,7,9,31;BYDAY=SU;BYHOUR=1,21,0;BYSECOND=0,59;BYSETPOS=1,-1,3,1000,,-1000", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=HOURLY;BIYMONTH=6;BYMONTHDAY=1,3;BYHOUR=2,14", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=HOURLY;BIYMONTH=6;BYMONTHDAY=1;;BYMINUTE=10;BYSECOND=11,12", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    cal.set(2010, 0, 1, 0, 0, 0);
    rangeEnd = cal.getTime();
    try {
        ZRecur test = new ZRecur("FREQ=YEARLY", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=YEARLY;BYYEARDAY=-1", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ZRecur test = new ZRecur("FREQ=SECONDLY", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    try {
        ParsedDateTime myDtStart = ParsedDateTime.parse("16010101T020000", tzmap, tzUTC, tzUTC);
        ZRecur test = new ZRecur("FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=12;BYDAY=-1SU", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(myDtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ParseException e) {
        System.out.println("Caught ParseException" + e);
        e.printStackTrace();
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
    cal.set(2010, 0, 1, 0, 0, 0);
    rangeEnd = cal.getTime();
    try {
        ZRecur test = new ZRecur("FREQ=YEARLY;BYMONTH=12;BYDAY=1WE", tzmap);
        System.out.println("\n\n" + test.toString() + "\n--------------------------------------------------------------");
        List<Date> dateList = test.expandRecurrenceOverRange(dtStart, rangeStart.getTime(), rangeEnd.getTime());
        for (Date d : dateList) {
            cal.setTime(d);
            System.out.printf("%tc\n", cal);
        }
    } catch (ServiceException e) {
        System.out.println("Caught ServiceException" + e);
        e.printStackTrace();
    }
}
Also used : ServiceException(com.zimbra.common.service.ServiceException) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) GregorianCalendar(java.util.GregorianCalendar) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ParseException(java.text.ParseException) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) Date(java.util.Date)

Example 40 with ParsedDateTime

use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.

the class ZRecur method parse.

private void parse(String str, TimeZoneMap tzmap) throws ServiceException {
    try {
        int numByParts = 0;
        for (String tok : str.split("\\s*;\\s*")) {
            String[] s = tok.split("\\s*=\\s*");
            if (s.length != 2) {
                if (ZimbraLog.calendar.isDebugEnabled())
                    ZimbraLog.calendar.debug(new Formatter().format("Parse error for recur: \"%s\" at token \"%s\"", str, tok));
                continue;
            }
            String rhs = s[1];
            // MS Exchange can add invalid spaces in RRULE part values.  Get rid of them.  (see bug 25169)
            rhs = rhs.replaceAll("\\s+", "");
            try {
                switch(Tokens.valueOf(s[0])) {
                    case FREQ:
                        mFreq = Frequency.valueOf(rhs);
                        break;
                    case UNTIL:
                        ParsedDateTime until = ParsedDateTime.parse(rhs, tzmap);
                        if (until != null) {
                            // be specified in an UTC time format."
                            if (until.hasTime())
                                until.toUTC();
                            mUntil = until;
                        }
                        break;
                    case COUNT:
                        mCount = Integer.parseInt(rhs);
                        break;
                    case INTERVAL:
                        mInterval = Integer.parseInt(rhs);
                        break;
                    case BYSECOND:
                        ++numByParts;
                        parseIntList(rhs, mBySecondList, 0, 59, false);
                        break;
                    case BYMINUTE:
                        ++numByParts;
                        parseIntList(rhs, mByMinuteList, 0, 59, false);
                        break;
                    case BYHOUR:
                        ++numByParts;
                        parseIntList(rhs, mByHourList, 0, 23, false);
                        break;
                    case BYDAY:
                        ++numByParts;
                        parseByDayList(rhs, mByDayList);
                        break;
                    case BYMONTHDAY:
                        ++numByParts;
                        parseIntList(rhs, mByMonthDayList, -31, 31, true);
                        break;
                    case BYYEARDAY:
                        ++numByParts;
                        parseIntList(rhs, mByYearDayList, -366, 366, true);
                        break;
                    case BYWEEKNO:
                        ++numByParts;
                        parseIntList(rhs, mByWeekNoList, -53, 53, true);
                        break;
                    case BYMONTH:
                        ++numByParts;
                        parseIntList(rhs, mByMonthList, 1, 12, false);
                        break;
                    case BYSETPOS:
                        ++numByParts;
                        parseIntList(rhs, mBySetPosList, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
                        break;
                    case WKST:
                        mWkSt = ZWeekDay.valueOf(rhs);
                        break;
                }
            } catch (IllegalArgumentException e) {
                ZimbraLog.calendar.warn("Skipping RECUR token: \"%s\" in Recur \"%s\" due to parse error", s[0], str, e);
            }
        }
        // 5) there is no other BYxxx part
        if (numByParts == 2 && Frequency.MONTHLY.equals(mFreq) && mByDayList.size() == 1 && mByDayList.get(0).mOrdinal == 0 && mBySetPosList.size() == 1) {
            mByDayList.get(0).mOrdinal = mBySetPosList.get(0);
            mBySetPosList.clear();
        }
    } catch (ParseException e) {
        throw ServiceException.FAILURE("Parse error for recur \"" + str + "\"", e);
    }
}
Also used : Formatter(java.util.Formatter) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ParseException(java.text.ParseException)

Aggregations

ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)66 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)23 Invite (com.zimbra.cs.mailbox.calendar.Invite)20 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)18 ParseException (java.text.ParseException)16 ArrayList (java.util.ArrayList)16 IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)15 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)14 Element (com.zimbra.common.soap.Element)13 RecurId (com.zimbra.cs.mailbox.calendar.RecurId)11 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)10 Account (com.zimbra.cs.account.Account)10 ZOrganizer (com.zimbra.cs.mailbox.calendar.ZOrganizer)10 ZVCalendar (com.zimbra.common.calendar.ZCalendar.ZVCalendar)9 ICalTok (com.zimbra.common.calendar.ZCalendar.ICalTok)8 ZAttendee (com.zimbra.cs.mailbox.calendar.ZAttendee)8 ZComponent (com.zimbra.common.calendar.ZCalendar.ZComponent)7 ZParameter (com.zimbra.common.calendar.ZCalendar.ZParameter)7 ServiceException (com.zimbra.common.service.ServiceException)7 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)7