locked
How to find gaps between multiple, variable DateRanges in C#? RRS feed

  • Question

  • Hello, I'm doing an appointment finder, where you can input multiple users' appointments and it should find empty gaps in a list with multiple and variable DateRanges. The methods I wrote do unfortunately not work. How could I do this without a large library like TimePeriodLibrary.

    This is the appointments collection:

    List < Range > appointments = new List < Range > ();
    
    // user 1
    appointments.Add(new Range(new DateTime(2020, 8, 3, 0, 0, 0), new DateTime(2020, 8, 4 + 1, 0, 0, 0)));
    appointments.Add(new Range(new DateTime(2020, 8, 7, 10, 0, 0), new DateTime(2020, 8, 7, 12, 0, 0)));
    
    // user 2
    appointments.Add(new Range(new DateTime(2020, 8, 3, 14, 0, 0), new DateTime(2020, 8, 3, 15, 30, 0)));
    appointments.Add(new Range(new DateTime(2020, 8, 6, 0, 0, 0), new DateTime(2020, 8, 6 + 1, 0, 0, 0)));
    appointments.Add(new Range(new DateTime(2020, 8, 6, 0, 0, 0), new DateTime(2020, 8, 6 + 1, 0, 0, 0)));
    
    // user 3
    appointments.Add(new Range(new DateTime(2020, 8, 3, 14, 0, 0), new DateTime(2020, 8, 3, 15, 30, 0)));
    appointments.Add(new Range(new DateTime(2020, 8, 6, 0, 0, 0), new DateTime(2020, 8, 6 + 1, 0, 0, 0)));
    appointments.Add(new Range(new DateTime(2020, 8, 6, 0, 0, 0), new DateTime(2020, 8, 6 + 1, 0, 0, 0)));
    
    // ...
    

    And this is my Range class:

    class Range {
    	private readonly DateTime _start;
    	private readonly DateTime _end;
    
    	public Range(DateTime start, DateTime end) {
    		if (start.CompareTo(end) >= 0) {
    			var temp = end;
    			end = start;
    			start = temp;
    		}
    
    		_start = start;
    		_end = end;
    	}
    
    	public DateTime Start {
    		get {
    			return _start;
    		}
    	}
    
    	public DateTime End {
    		get {
    			return _end;
    		}
    	}
    }

    Thanks for any help :)

    Monday, August 10, 2020 11:42 AM

Answers

All replies

  • Hi TheSteveXYZ,
    In order to avoid misunderstandings, do you want to find out "gaps" time between the two time periods? 
    Such as:
    User1:

    appointments.Add(new Range(new DateTime(2020, 8, 3, 0, 0, 0), new DateTime(2020 , 8, 5, 0, 0, 0)));

    User2

    appointments.Add(new Range(new DateTime(2020, 8, 7, 10, 0, 0), new DateTime(2020, 8, 7, 12, 0, 0)));

    The result should be like this:"start time: 2020, 8, 5, 0, 0, 0  end time :2020, 8, 7, 10, 0, 0".

    If so, there are some methods in this links you can refer to.
    [How to get gap in date ranges from a period of time]
    [Find Gap Date Ranges from two Set of Date Ranges C#]

    If not, please explain in detail.
    Best Regards,
    Daniel Zhang


    "Windows Forms General" forum will be migrating to a new home on Microsoft Q&A (Preview)!
    We invite you to post new questions in the "Windows Forms General" forum’s new home on Microsoft Q&A (Preview)!
    For more information, please refer to the sticky post.

    Tuesday, August 11, 2020 8:39 AM
  • Hi

    What is your requirements can explain briefly

    Thanks  and regards

    Tuesday, August 11, 2020 6:04 PM
  • Thank you.

    I used the Extension method from your second link (https://stackoverflow.com/a/15452877/11304248 (can't hyperlink it because my account here is new)) and replaced the AddDays with AddMinutes to also search for gaps in days. 

    I came up with the following class:

    public static class DateRangeEnumerable
        {
            public static IEnumerable<DateTime> GetDates(this IEnumerable<DateRange> source)
            {
                var sortedSource = source.OrderBy(r => r.StartDate);
    
                foreach (var range in sortedSource)
                {
                    var d = range.StartDate;
                    while (d < range.EndDate)
                    {
                        yield return d;
                        //d = d.AddDays(1);
                        d = d.AddMinutes(1);
                    }
                }
            }
    
            public static IEnumerable<DateRange> GetRanges(this IEnumerable<DateTime> source)
            {
                var sortedSource = source.OrderBy(d => d);
                var enumerator = sortedSource.GetEnumerator();
    
                if (!enumerator.MoveNext())
                    yield break;
    
                DateTime from = enumerator.Current;
                DateTime prev = from;
    
                while (true)
                {
                    while (true)
                    {
                        if (enumerator.MoveNext())
                        {
                            //if (enumerator.Current == prev.AddDays(1))
                            if (enumerator.Current == prev.AddMinutes(1))
                                prev = enumerator.Current;
                            else
                                break;
                        }
                        else
                        {
                            //yield return new DateRange(from, prev.AddDays(1));
                            yield return new DateRange(from, prev.AddMinutes(1));
                            yield break;
                        }
    
                    }
    
                    //yield return new DateRange(from, prev.AddDays(1));
                    yield return new DateRange(from, prev.AddMinutes(1));
    
                    from = enumerator.Current;
                    prev = enumerator.Current;
                }
            }
        }

    And it works fine with the rest of my code.

    Wednesday, August 12, 2020 6:36 AM