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; }
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; }