-1

I'm currently programming an appointment finder that automatically syncs with MS Exchange Server. The program should lookup multiple users' calendar when they are available. I have coded some demo data with multiple users and their appointments. The appointments consist of two DateTimes.

So my question is: How can I find a gap between multiple users appointments, where everyone is available. This is the demo data:

        var appointment1ForPerson1 = new Appointment(1, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0))) });
        var appointment2ForPerson1 = new Appointment(3, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0))) });
        var appointment3ForPerson1 = new Appointment(5, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0))) });

        var appointmentsForPerson1 = new List<Appointment>() { appointment1ForPerson1, appointment2ForPerson1, appointment3ForPerson1 };
        var person1 = new Person("steven@example.de", appointmentsForPerson1);
        _userList.Add(person1);

        var appointment1ForPerson2 = new Appointment(1, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0))) });
        var appointment2ForPerson2 = new Appointment(3, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0))) });
        var appointment3ForPerson2 = new Appointment(5, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0))) });

        var appointmentsForPerson2 = new List<Appointment>() { appointment1ForPerson2, appointment2ForPerson2, appointment3ForPerson2 };
        var person2 = new Person("jonas@example.de", appointmentsForPerson2);
        _userList.Add(person2);

Here is the Person class with the Appointment and Time:

class Person
{
    private readonly string _email;
    private readonly List<Appointment> _appointments;

    public Person(string email, List<Appointment> appointments)
    {
        _email = email;
        _appointments = appointments;
    }

    public string Email
    {
        get { return _email; }
    }

    public List<Appointment> Appointments
    {
        get { return _appointments; }
    }

    internal class Appointment
    {
        private readonly List<Time> _appointmentHoursList;

        public Appointment(List<Time> appointmentHoursList)
        {
            _appointmentHoursList = appointmentHoursList;
        }

        public List<Time> AppointmentHoursList
        {
            get { return _appointmentHoursList; }
        }

        internal class Time
        {
            private readonly DateTime _beginningTime;
            private readonly DateTime _endTime;

            public Time(DateTime beginningTime, DateTime endTime)
            {
                _beginningTime = beginningTime;
                _endTime = endTime;
            }

            public DateTime BeginningTime
            {
                get { return _beginningTime; }
            }

            public DateTime EndTime
            {
                get { return _endTime; }
            }
        }
    }
}
Steven2105
  • 540
  • 5
  • 20
  • 1
    And what have you tried? Where did you stuck? – Maciej Los Jul 08 '20 at 11:41
  • Is this exchange online? There is an API for that already. – Crowcoder Jul 08 '20 at 11:41
  • I need a function which can find a gap between users' appointments. – Steven2105 Jul 08 '20 at 11:41
  • 2
    You need to find [intersections](https://en.wikipedia.org/wiki/Intersection_(set_theory)) of free time for all users. Start with introducing `Interval` type with `Intersect` operation. – Sinatr Jul 08 '20 at 11:42
  • @Crowcoder I'll be using the MAPI later, but currently I'm testing it with some demo data. – Steven2105 Jul 08 '20 at 11:43
  • What's the dayNumber for here? – Chetan Jul 08 '20 at 11:44
  • @ChetanRanpariya what do you mean? – Steven2105 Jul 08 '20 at 11:45
  • If you are using O365 the MS Graph API has an API for finding appointment times for multiple people. If you are using on-prem Exchange then disregard. – Crowcoder Jul 08 '20 at 11:45
  • I was wondering what's the use of dayNumber value in Appointment class. Also can you share the expected output of the given input? – Chetan Jul 08 '20 at 11:47
  • Have you seen this: [Time Period Library for .NET](https://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET)? – Maciej Los Jul 08 '20 at 11:50
  • @ChetanRanpariya It was a unused function. I removed it now. The input is the demo data shown above and the output should be an appointment of my Time class, where every user is available for a meeting. – Steven2105 Jul 08 '20 at 11:51
  • @MaciejLos No, I didn't. – Steven2105 Jul 08 '20 at 11:54
  • I am pretty sure you can ask the API to give you conflicts if any. Try looking into the API for help. – CodingYoshi Jul 08 '20 at 12:29
  • Does this answer your question? [Find Gap Date Ranges from two Set of Date Ranges C#](https://stackoverflow.com/questions/15446054/find-gap-date-ranges-from-two-set-of-date-ranges-c-sharp) – Maciej Los Jul 08 '20 at 12:31
  • @MaciejLos Not really. I used an answer from that post: https://hastebin.com/abucahunus.cs However, I do not understand where I should put the dates. Let's say I have 3 people where each of them has 2 appointments. Where should I add the dates then? – Steven2105 Jul 08 '20 at 13:54

1 Answers1

1

Below solution is using TimePeriodLibraryforNET. Please, read comments in the code:

//define working hours -  obligatory part!
TimePeriodCollection workinghours = new TimePeriodCollection();
for(int i = 7; i<12; i+=2)
    workinghours.Add(new TimeRange(new DateTime(2020, 7, i, 9, 0, 0), new DateTime(2020, 7, i, 17, 0, 0)));
ITimePeriodCollection workingperiods = new TimePeriodCombiner<TimeRange>().CombinePeriods(workinghours);

//define user#1 appointments
TimePeriodCollection allappointments = new TimePeriodCollection();
allappointments.Add(new TimeRange(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0)));   
//define user#2 appointments
allappointments.Add(new TimeRange(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 15, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 30, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 11, 10, 30, 0), new DateTime(2020, 7, 11, 11, 45, 0)));
//combine periods  
ITimePeriodCollection usersperiods = new TimePeriodCombiner<TimeRange>().CombinePeriods(allappointments);

//get gaps
TimePeriodCollection gaps = new TimePeriodCollection();
foreach (ITimePeriod basePeriod in workingperiods)
{
    gaps.AddAll( new TimeGapCalculator<TimeRange>().GetGaps(usersperiods, basePeriod));
}
//enumerate gaps
foreach(ITimePeriod gap in gaps)
{
    Console.WriteLine($"Gap: {gap}");
}

Result (based on example data):

Gap: 2020-07-07 09:00:00 - 16:45:00 | 0.07:45
Gap: 2020-07-09 12:30:00 - 17:00:00 | 0.04:30
Gap: 2020-07-11 09:00:00 - 10:00:00 | 0.01:00
Gap: 2020-07-11 12:00:00 - 17:00:00 | 0.05:00
Maciej Los
  • 8,468
  • 1
  • 20
  • 35