internal static DateTime GetNextSingleYearlyRecurrence(AppointmentRecurrence recurrence, DateTime startDate)
        {
            YearlyRecurrenceSettings yearly = recurrence.Yearly;
            Calendar cal = GetCalendar();

            if (startDate.Month < yearly.RepeatOnMonth)
            {
                startDate = startDate.AddMonths((yearly.RepeatOnMonth - startDate.Month) - 1);
                return GetNextMonthlyRecurrence(startDate, yearly.RepeatOnRelativeDayInMonth, yearly.RelativeDayOfWeek, yearly.RepeatOnDayOfMonth, eMonthRecurrence.All);
            }
            else if (startDate.Month == yearly.RepeatOnMonth)
            {
                DateTime refDate = startDate.AddDays(-(startDate.Day));
                DateTime ret = GetNextMonthlyRecurrence(refDate, yearly.RepeatOnRelativeDayInMonth, yearly.RelativeDayOfWeek, yearly.RepeatOnDayOfMonth, eMonthRecurrence.All);
                if (ret > startDate) return ret;
            }

            // Forward to next year and right month
            startDate = startDate.AddDays(cal.GetDaysInYear(startDate.Year) - startDate.DayOfYear).AddMonths(yearly.RepeatOnMonth - 1);
            return GetNextMonthlyRecurrence(startDate, yearly.RepeatOnRelativeDayInMonth, yearly.RelativeDayOfWeek, yearly.RepeatOnDayOfMonth, eMonthRecurrence.All);
        }
 /// <summary>
 /// Initializes a new instance of the YearlyRecurrenceSettings class.
 /// </summary>
 /// <param name="recurrence"></param>
 public YearlyRecurrenceSettings(AppointmentRecurrence recurrence)
 {
     _Recurrence = recurrence;
 }
        /// <summary>
        /// Generates Yearly recurring appointments. If appointment is assigned to calendar method must populate the Calendar.Appointments collection as well.
        /// </summary>
        /// <param name="subsetCollection">Collection to add generated recurrences to</param>
        /// <param name="recurrence">Recurrence description, must be of Monthly recurrence type.</param>
        /// <param name="startDate">Start date for generation.</param>
        /// <param name="endDate">End date for generation.</param>
        public void GenerateYearlyRecurrence(AppointmentSubsetCollection subsetCollection, AppointmentRecurrence recurrence, DateTime startDate, DateTime endDate)
        {
            Appointment app = recurrence.Appointment;
            DateTime recurrenceStartDate = DateTimeHelper.MaxDate(recurrence.RecurrenceStartDate, app.EndTime.AddDays(1).Date);
            if (recurrenceStartDate > endDate) return;

            if (!(startDate.Month <= recurrence.Yearly.RepeatOnMonth && endDate.Month >= recurrence.Yearly.RepeatOnMonth) && endDate.Subtract(startDate).TotalDays < 28)
                return;
            int totalRecurrences = 0;
            // Check the range first
            if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate)
            {
                if (startDate > recurrence.RangeEndDate) return;
            }
            else if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences && recurrence.RangeNumberOfOccurrences > 0 && recurrenceStartDate < startDate)
            {
                int count = recurrence.RangeNumberOfOccurrences + 1;
                DateTime testDate = DateTimeHelper.BeginningOfDay(recurrenceStartDate.AddDays(-(recurrenceStartDate.Day - 1))).AddMonths(-1);
                if (testDate < app.EndTime)
                    testDate = app.EndTime.Date.AddDays(1);
                DateTime startDateOnly = DateTimeHelper.BeginningOfDay(startDate);
                while (count > 0 && testDate < startDateOnly)
                {
                    testDate = GetNextYearlyRecurrence(recurrence, testDate);
                    if (testDate >= startDateOnly) break;
                    count--;
                    totalRecurrences++;
                }
                if (count == 0) return;
            }

            DateTime currentDate = DateTimeHelper.MaxDate(startDate, recurrenceStartDate).AddDays(-1);
            if (recurrence.Yearly.RepeatInterval > 1)
                currentDate = recurrenceStartDate;
            do
            {
                currentDate = GetNextYearlyRecurrence(recurrence, currentDate);

                if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate && currentDate > recurrence.RangeEndDate ||
                    recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences && totalRecurrences >= recurrence.RangeNumberOfOccurrences)
                    break;

                if (currentDate >= startDate && currentDate <= endDate && !IsIgnoredRecurrence(currentDate, recurrence))
                {
                    subsetCollection.Add(CreateRecurringAppointmentInstance(currentDate, app));
                    totalRecurrences++;
                }
            } while (currentDate <= endDate);
        }
 internal static DateTime GetNextYearlyRecurrence(AppointmentRecurrence recurrence, DateTime startDate)
 {
     YearlyRecurrenceSettings yearly = recurrence.Yearly;
     if (yearly.RepeatInterval > 1)
     {
         DateTime currentDate = startDate;
         for (int i = 0; i < yearly.RepeatInterval; i++)
         {
             currentDate = GetNextSingleYearlyRecurrence(recurrence, currentDate);
         }
         return currentDate;
     }
     else
     {
         return GetNextSingleYearlyRecurrence(recurrence, startDate);
     }
 }
        /// <summary>
        /// Generates Monthly recurring appointments. If appointment is assigned to calendar method must populate the Calendar.Appointments collection as well.
        /// </summary>
        /// <param name="subsetCollection">Collection to add generated recurrences to</param>
        /// <param name="recurrence">Recurrence description, must be of Monthly recurrence type.</param>
        /// <param name="startDate">Start date for generation.</param>
        /// <param name="endDate">End date for generation.</param>
        public void GenerateMonthlyRecurrence(AppointmentSubsetCollection subsetCollection, AppointmentRecurrence recurrence, DateTime startDate, DateTime endDate)
        {
            Appointment app = recurrence.Appointment;
            DateTime recurrenceStartDate = DateTimeHelper.MaxDate(recurrence.RecurrenceStartDate, app.EndTime/*.AddDays(1).Date*/);
            if (recurrenceStartDate > endDate) return;

            int totalRecurrences = 0;
            // Check the range first
            if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate)
            {
                if (startDate > recurrence.RangeEndDate) return;
            }
            else if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences && recurrence.RangeNumberOfOccurrences > 0)
            {
                int count = recurrence.RangeNumberOfOccurrences + 1;
                DateTime testDate = DateTimeHelper.BeginningOfDay(recurrenceStartDate);
                DateTime startDateOnly = DateTimeHelper.BeginningOfDay(startDate);
                while (count > 0 && testDate < startDateOnly)
                {
                    int repeatInterval = recurrence.Monthly.RepeatInterval;
                    while (repeatInterval > 0)
                    {
                        testDate = GetNextMonthlyRecurrence(recurrence, testDate);
                        repeatInterval--;
                    }
                    if (testDate < startDate)
                        totalRecurrences++;
                    count--;
                }
                if (count == 0) return;
            }

            DateTime currentDate = recurrenceStartDate;// DateTimeHelper.MaxDate(recurrenceStartDate, startDate).AddMonths(-1);

            do
            {
                int repeatCount = recurrence.Monthly.RepeatInterval;
                do
                {
                    repeatCount--;
                    currentDate = GetNextMonthlyRecurrence(recurrence, currentDate);
                } while (repeatCount > 0);

                if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate && currentDate > recurrence.RangeEndDate ||
                    recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences && totalRecurrences >= recurrence.RangeNumberOfOccurrences)
                    break;

                if (currentDate >= startDate && currentDate <= endDate && !IsIgnoredRecurrence(currentDate, recurrence))
                {
                    subsetCollection.Add(CreateRecurringAppointmentInstance(currentDate, app));
                    totalRecurrences++;
                }
            } while (currentDate <= endDate);
        }
 private DateTime GetNextMonthlyRecurrence(AppointmentRecurrence recurrence, DateTime startDate)
 {
     MonthlyRecurrenceSettings monthly = recurrence.Monthly;
     return GetNextMonthlyRecurrence(startDate, monthly.RepeatOnRelativeDayInMonth,
         monthly.RelativeDayOfWeek, monthly.RepeatOnDayOfMonth, monthly.RepeatOnMonths);
 }
        /// <summary>
        /// Generates Daily recurring appointments. If appointment is assigned to calendar method must populate the Calendar.Appointments collection as well.
        /// </summary>
        /// <param name="subsetCollection">Collection to add generated recurrences to</param>
        /// <param name="recurrence">Recurrence description, must be of Daily recurrence type.</param>
        /// <param name="startDate">Start date for generation.</param>
        /// <param name="endDate">End date for generation.</param>
        public void GenerateDailyRecurrence(AppointmentSubsetCollection subsetCollection, AppointmentRecurrence recurrence, DateTime startDate, DateTime endDate)
        {
            Appointment app = recurrence.Appointment;
            int appointmentDaysDuration = (int)Math.Max(0, Math.Ceiling(app.EndTime.Date.Subtract(app.StartTime.Date).TotalDays));
            DateTime recurrenceStartDate = DateTimeHelper.MaxDate(recurrence.RecurrenceStartDate, DateTimeHelper.IsBeginningOfDay(app.EndTime) ? app.EndTime : app.EndTime.AddDays(recurrence.Daily.RepeatInterval).Date);

            if (recurrenceStartDate > endDate) return;

            int repeats = 0;

            // Check the range first
            if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate)
            {
                if (startDate > recurrence.RangeEndDate) return;
            }
            else if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences)
            {
                DateTime rangeStartDate = DateTimeHelper.MaxDate(recurrence.RecurrenceStartDate, DateTimeHelper.IsBeginningOfDay(app.LocalEndTime) ? app.LocalEndTime : app.LocalEndTime.AddDays(recurrence.Daily.RepeatInterval).Date);
                int totalDays = (int)Math.Ceiling(startDate.Subtract(rangeStartDate).TotalDays);

                switch (recurrence.Daily.RepeatOnDaysOfWeek)
                {
                    case eDailyRecurrenceRepeat.All:
                        repeats = Math.Max(0, totalDays / (recurrence.Daily.RepeatInterval + appointmentDaysDuration));

                        if (repeats >= recurrence.RangeNumberOfOccurrences)
                            return;
                        break;

                    case eDailyRecurrenceRepeat.WeekDays:
                        repeats = Math.Max(0, DateTimeHelper.TotalWeekDays(recurrenceStartDate, startDate) / (recurrence.Daily.RepeatInterval + appointmentDaysDuration));

                        // Assume weekdays repeat
                        if (repeats > recurrence.RangeNumberOfOccurrences)
                            return;
                        break;

                    default:
                        repeats = Math.Max(0, DateTimeHelper.TotalWeekDays(recurrenceStartDate, startDate));
                        repeats = Math.Max(0, totalDays - repeats);

                        // Assume weekend days repeat
                        if (repeats > recurrence.RangeNumberOfOccurrences)
                            return;
                        break;
                }

                //repeats = 0;
            }

            DateTime currentDay = recurrenceStartDate; // DateTimeHelper.MaxDate(startDate, recurrenceStartDate);

            while (currentDay <= endDate)
            {
                if (currentDay >= startDate || currentDay < startDate && IsRecurringOnDay(currentDay, startDate, endDate, app))
                {
                    if (!IsRecurringOnDay(currentDay, startDate, endDate, app)) break;
                    if (recurrence.Daily.RepeatOnDaysOfWeek == eDailyRecurrenceRepeat.All ||
                        (recurrence.Daily.RepeatOnDaysOfWeek == eDailyRecurrenceRepeat.WeekDays && !DateTimeHelper.IsWeekendDay(currentDay)) ||
                        (recurrence.Daily.RepeatOnDaysOfWeek == eDailyRecurrenceRepeat.WeekendDays && DateTimeHelper.IsWeekendDay(currentDay)))
                    {
                        if (!IsIgnoredRecurrence(currentDay, recurrence))
                        {
                            subsetCollection.Add(CreateRecurringAppointmentInstance(currentDay, app));
                            repeats++;
                        }
                    }
                }

                switch (recurrence.Daily.RepeatOnDaysOfWeek)
                {
                    case eDailyRecurrenceRepeat.All:
                        currentDay = currentDay.AddDays(recurrence.Daily.RepeatInterval + appointmentDaysDuration);
                        break;

                    case eDailyRecurrenceRepeat.WeekDays:
                        //currentDay = currentDay.AddDays(currentDay.DayOfWeek == DayOfWeek.Saturday ? 2 : Math.Max(1, recurrence.Daily.RepeatInterval + appointmentDaysDuration));
                        currentDay = currentDay.AddDays(Math.Max(1, recurrence.Daily.RepeatInterval + appointmentDaysDuration)); // Changed for consistency
                        break;

                    case eDailyRecurrenceRepeat.WeekendDays:
                        while (true)
                        {
                            currentDay = currentDay.AddDays(1);

                            if (DateTimeHelper.IsWeekendDay(currentDay) == true)
                                break;
                        }
                        break;
                }

                if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate && currentDay > recurrence.RangeEndDate ||
                    recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences && repeats >= recurrence.RangeNumberOfOccurrences)
                    break;
            }
        }
        /// <summary>
        /// Generates Weekly recurring appointments. If appointment is assigned to calendar method must populate the Calendar.Appointments collection as well.
        /// </summary>
        /// <param name="subsetCollection">Collection to add generated recurrences to</param>
        /// <param name="recurrence">Recurrence description, must be of Weekly recurrence type.</param>
        /// <param name="startDate">Start date for generation.</param>
        /// <param name="endDate">End date for generation.</param>
        public void GenerateWeeklyRecurrence(AppointmentSubsetCollection subsetCollection, AppointmentRecurrence recurrence, DateTime startDate, DateTime endDate)
        {
            Appointment app = recurrence.Appointment;

            DateTime baseStartDate = app.EndTime.Date;
            if (app.EndTime.Date > app.StartTime.Date && app.EndTime.TimeOfDay > app.StartTime.TimeOfDay && baseStartDate != DateTime.MinValue)
                baseStartDate = baseStartDate.AddDays(1);
            DateTime recurrenceStartDate = baseStartDate;
            int repeatInterval = recurrence.Weekly.RepeatInterval;

            if (RepeatsOnSingleDayOnly(recurrence.Weekly.RepeatOnDaysOfWeek) && !(app.StartTime.Date == startDate.Date && endDate.Date == startDate.Date))
                recurrenceStartDate = baseStartDate.AddMilliseconds(-1).AddDays((repeatInterval) * 7 /*+ (recurrence.Weekly.RepeatInterval > 1 ? (8 - (int)baseStartDate.DayOfWeek) : 1)*/).Date;
            else
            {
                if (app.EndTime.Date > app.StartTime.Date && app.EndTime.TimeOfDay < app.StartTime.TimeOfDay)
                    recurrenceStartDate = app.StartTime.Date.AddDays(1);
                else
                    recurrenceStartDate = app.EndTime.Date.AddDays(1);
            }

            recurrenceStartDate = DateTimeHelper.MaxDate(recurrence.RecurrenceStartDate, recurrenceStartDate);

            if (recurrenceStartDate > endDate) return;

            int totalRecurrences = 0;
            // Check the range first
            if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate)
            {
                if (startDate > recurrence.RangeEndDate) return;
            }
            else if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences && repeatInterval == 1)
            {
                int totalDays = (int)Math.Ceiling(endDate.Subtract(recurrenceStartDate).TotalDays);
                int occurrencesPerWeek = GetNumberOfDays(recurrence.Weekly.RepeatOnDaysOfWeek);
                if (occurrencesPerWeek == 0)
                    throw new ArgumentException("Weekly recurrence must have at least single day selected using RepeatOnDaysOfWeek property.");
                totalRecurrences = DateTimeHelper.TotalNumberOfDays(recurrenceStartDate, endDate, recurrence.Weekly.RepeatOnDaysOfWeek);
                if (totalRecurrences > recurrence.RangeNumberOfOccurrences) return;
            }

            bool countTotalRecurrences = false;
            if (repeatInterval > 1 && recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences)
                countTotalRecurrences = true;

            DateTime currentDay = recurrenceStartDate;// DateTimeHelper.MaxDate(recurrenceStartDate, startDate);
            while (currentDay <= endDate)
            {
                if (currentDay >= startDate && DateTimeHelper.HasDay(currentDay.DayOfWeek, recurrence.Weekly.RepeatOnDaysOfWeek) &&
                    !IsIgnoredRecurrence(currentDay, recurrence))
                {
                    subsetCollection.Add(CreateRecurringAppointmentInstance(currentDay, app));
                    totalRecurrences++;
                }
                else if (countTotalRecurrences && currentDay < startDate && DateTimeHelper.HasDay(currentDay.DayOfWeek, recurrence.Weekly.RepeatOnDaysOfWeek)
                             && !IsIgnoredRecurrence(currentDay, recurrence))
                {
                    totalRecurrences++;
                    if (totalRecurrences >= recurrence.RangeNumberOfOccurrences)
                        return;
                }

                if (currentDay.DayOfWeek != DayOfWeek.Sunday)
                {
                    while (currentDay.DayOfWeek != DayOfWeek.Sunday)
                    {
                        currentDay = currentDay.AddDays(1);
                        if (currentDay > endDate || recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate && currentDay > recurrence.RangeEndDate)
                            break;
                        if (currentDay >= startDate && DateTimeHelper.HasDay(currentDay.DayOfWeek, recurrence.Weekly.RepeatOnDaysOfWeek)
                             && !IsIgnoredRecurrence(currentDay, recurrence))
                        {
                            subsetCollection.Add(CreateRecurringAppointmentInstance(currentDay, app));
                        }
                        else if (countTotalRecurrences && currentDay < startDate && DateTimeHelper.HasDay(currentDay.DayOfWeek, recurrence.Weekly.RepeatOnDaysOfWeek)
                             && !IsIgnoredRecurrence(currentDay, recurrence))
                        {
                            totalRecurrences++;
                            if (totalRecurrences >= recurrence.RangeNumberOfOccurrences)
                                return;
                        }
                    }
                }
                currentDay = currentDay.AddDays(1 + (repeatInterval - 1) * 7);
                if (recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeEndDate && currentDay > recurrence.RangeEndDate ||
                    recurrence.RangeLimitType == eRecurrenceRangeLimitType.RangeNumberOfOccurrences && totalRecurrences > recurrence.RangeNumberOfOccurrences)
                    break;
            }
        }
 private static bool IsIgnoredRecurrence(DateTime currentDay, AppointmentRecurrence recurrence)
 {
     if (recurrence.SkippedRecurrences.Count == 0) return false;
     foreach (DateTime date in recurrence.SkippedRecurrences)
     {
         if (date.Date == currentDay.Date)
             return true;
     }
     return false;
 }
示例#10
0
        private void OnRecurrenceChanged(AppointmentRecurrence oldValue, AppointmentRecurrence newValue)
        {
            if (oldValue != null)
            {
                oldValue.Appointment = null;
                oldValue.SubPropertyChanged -= this.ChildPropertyChangedEventHandler;
            }

            if (newValue != null)
            {
                if (newValue.Appointment != null)
                    throw new ArgumentException("Recurrence value already assigned to the appointment. Recurrence can be assigned to single appointment only");
                newValue.Appointment = this;
                newValue.SubPropertyChanged += this.ChildPropertyChangedEventHandler;
            }
            OnPropertyChanged(new PropertyChangedEventArgs("Recurrence"));
        }
 /// <summary>
 /// Initializes a new instance of the MonthlyRecurrenceSettings class.
 /// </summary>
 /// <param name="recurrence"></param>
 public MonthlyRecurrenceSettings(AppointmentRecurrence recurrence)
 {
     _Recurrence = recurrence;
 }