Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate location and number of intersections between multiple date/time ranges?

Tags:

c#

.net

vb.net

I need to calculate the location of intersections between multiple date ranges, and the number of overlapping intersections. Then I need to show which date/time ranges overlap each of those intersecting sections. It is slightly more complicated than that so I'll do my best to explain by providing an example. I am working in VB.Net, but C# examples are acceptable as well as I work in both.

We have several high risk tasks that involve the same system. Below I have three example jobs named HR1/2/3/4 with start and end date/times.

  • HR1 {1/6/2010 10:00 - 1/6/2010 15:00}
  • HR2 {1/6/2010 11:00 - 1/6/2010 18:00}
  • HR3 {1/6/2010 12:00 - 1/6/2010 14:00}
  • HR4 {1/6/2010 18:00 - 1/6/2010 20:00}

What I want the end result to be is shown below. I am having trouble describing it any way but by example.

  • HRE1 {1/6/2010 10:00 - 1/6/2010 11:00} - Intersects 1
  • {End Time Split 1, for readability only, not needed in solution}
  • HRE1 {1/6/2010 11:00 - 1/6/2010 12:00} - Intersects 2
  • HRE2 {1/6/2010 11:00 - 1/6/2010 12:00} - Intersects 2
  • {End Time Split 2, for readability only, not needed in solution}
  • HRE1 {1/6/2010 12:00 - 1/6/2010 14:00} - Intersects 3
  • HRE2 {1/6/2010 12:00 - 1/6/2010 14:00} - Intersects 3
  • HRE3 {1/6/2010 12:00 - 1/6/2010 14:00} - Intersects 3
  • {End Time Split 3, for readability only, not needed in solution}
  • HRE1 {1/6/2010 14:00 - 1/6/2010 15:00} - Intersects 2
  • HRE2 {1/6/2010 14:00 - 1/6/2010 15:00} - Intersects 2
  • {End Time Split 4, for readability only, not needed in solution}
  • HRE2 {1/6/2010 15:00 - 1/6/2010 18:00} - Intersects 1
  • {End Time Split 5, for readability only, not needed in solution}
  • HR4 {1/6/2010 18:00 - 1/6/2010 20:00} - Intersects 1

Any help would be greatly appreciated.

like image 408
Peter Avatar asked Apr 29 '10 15:04

Peter


1 Answers

var timePoints = (from r in ranges select r.Start)
    .Concat(from r in ranges select r.End)
    .Distinct().OrderBy(dt => dt).ToArray();

var intersections = from i in Enumerable.Range(0, timePoints.Length - 1)
                    let start = timePoints[i]
                    let end = timePoints[i + 1]
                    from range in ranges
                    where range.Start <= start && range.End >= end
                    select new { Range = range, Start = start, End = end };

EDIT: Modified code that counts intersections:

var timePoints = (from r in ranges select r.Start)
    .Concat(from r in ranges select r.End)
    .Distinct().OrderBy(dt => dt).ToArray();

var intersectionGroups = from i in Enumerable.Range(0, timePoints.Length - 1)
                         let start = timePoints[i]
                         let end = timePoints[i + 1]
                         select new
                         {
                             Start = start,
                             End = end,
                             Ranges =
                                 from range in ranges
                                 where range.Start <= start && range.End >= end
                                 select range
                         };

var intersections = from intGroup in intersectionGroups
                    let count = intGroup.Ranges.Count()
                    from range in intGroup.Ranges
                    select new
                    {
                        Range = range,
                        Start = intGroup.Start,
                        End = intGroup.End,
                        Count = count
                    };

I don't know what do you want to do with the result, but it may be better to use intersectionGroups rather than intersections.

like image 113
svick Avatar answered Nov 20 '22 03:11

svick