BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Algorithms and Data Structures
.NET 3.5+

An Extensible Appointment Scheduling Library

Scheduling software can be used to plan future appointments, including those appointments that repeat on a regular basis. This article describes a library with four types of scheduling rule and the potential for additional rules to be incorporated.

Recurring Schedules

The next task is to add the base class for recurring schedules and our first repeating appointment rule.

RepeatingSchedule Class

The RepeatingSchedule class is the base class for schedules that may generate multiple appointments. This abstract class inherits functionality from the Schedule type, adding one extra property to hold a scheduling range. The scheduling range is a period of dates between which appointments may be generated. If the date being checked is outside of this range, even if it fulfils any other rules of the schedule, no appointment will be generated. This allows for temporary schedules that start on a given date and cease at a later date. The DateIsInPeriod method checks that a date is within the scheduling period. This protected method is available to subclasses.

public abstract class RepeatingSchedule : Schedule
{
    public Period SchedulingRange { get; set; }

    protected bool DateIsInPeriod(DateTime date)
    {
        return date >= SchedulingRange.Start && date <= SchedulingRange.End;
    }
}

SimpleRepeatingSchedule Class

We'll now implement our first concrete recurring schedule. The SimpleRepeatingSchedule class is designed to allow for regularly repeating appointments. The earliest appointment that may be generated falls on the start date of the scheduling period. Further appointments are at regular intervals. The interval is measured in days and the number of days is held in the DaysBetween property.

The OccursOnDate method performs two checks. Firstly, it calls the protected method, DateIsInPeriod. If the date being checked is not within the scheduling period, the method returns false. If it is within the scheduling period, the private DateIsValidForSchedule method is called. This calculates the number of days between the scheduling period start date and the date being checked. If this is a multiple of the DaysBetween value, the date requires an appointment.

public class SimpleRepeatingSchedule : RepeatingSchedule
{
    int _daysBetween;

    public int DaysBetween
    {
        get
        {
            return _daysBetween; 
        }
        set
        {
            if (value <= 0) throw new ArgumentException(
                "The days between appointments must be at least one.");
                
            _daysBetween = value;
        }
    }

    public override bool OccursOnDate(DateTime date)
    {
        if (DateIsInPeriod(date))
        {
            return DateIsValidForSchedule(date);
        }
        return false;
    }

    private bool DateIsValidForSchedule(DateTime date)
    {
        int daysBetweenFirstAndCheckDate
            = (int)date.Subtract(SchedulingRange.Start).TotalDays;
        return daysBetweenFirstAndCheckDate % DaysBetween == 0;
    }
}

Second Test

We can now perform a second test, this time adding a simple repeating schedule. Add the following schedule, which generates an appointment on every Monday in 2012, just after the previous schedules in the Main method.

var simple = new SimpleRepeatingSchedule
{
    Name = "Sprint Planning Meeting",
    TimeOfDay = new TimeSpan(10, 0, 0),
    SchedulingRange = new Period(new DateTime(2012, 1, 2), new DateTime(2012, 12, 31)),
    DaysBetween = 7
};

Now we need to update the schedule list to include the new schedule. Change the line as follows:

var schedules = new List<Schedule> { single1, single2, simple };

Executing the program now generates a "Sprint Planning Meeting" appointment for every Monday within the period, in addition to the original two single appointments.

2012-05-07 10:00 | Sprint Planning Meeting
2012-05-08 19:30 | Meet Bob for Pint
2012-05-12 09:30 | Confirm Meeting
2012-05-14 10:00 | Sprint Planning Meeting
2012-05-21 10:00 | Sprint Planning Meeting
2012-05-28 10:00 | Sprint Planning Meeting
2012-06-04 10:00 | Sprint Planning Meeting
2012-06-11 10:00 | Sprint Planning Meeting
2012-06-18 10:00 | Sprint Planning Meeting
2012-06-25 10:00 | Sprint Planning Meeting

WeeklySchedule Class

To complete the scheduling library we need to add the final two recurring schedule classes. The first of these is WeeklySchedule. This class allows you to select any combination of the seven days of the week and create appointments only on those days. The list is set using the SetDays method. OccursOnDate checks that the day of the week of the supplied date is present within the list and that the date falls within the scheduling period.

public class WeeklySchedule : RepeatingSchedule
{
    List<DayOfWeek> _days;

    public void SetDays(IEnumerable<DayOfWeek> days)
    {
        _days = days.Distinct().ToList();
    }

    public override bool OccursOnDate(DateTime date)
    {
        return DateIsInPeriod(date) && _days.Contains(date.DayOfWeek);
    }
}
29 April 2012