How to find out if there is any overlap in a period collection using LINQ

I have a set of periods [FromDate, ToDate].

I would know if there is any match between the given period and the periods in the collection.

I already started with this:

 // periodToCheck is the given item
 bool conflict = Periods.Any(p => ((p.FromDate >= periodToCheck.fromDate && 
                                    p.FromDate <= periodToCheck.toDate)
                                  ||
                                   (p.ToDate >= periodToCheck.fromDate && 
                                    p.ToDate <= periodToCheck.toDate))
                             );

The problem is that it does not cover the whole situation, for example:

[2010.1.1], [2010.1.31]
[2010.1.5], [2010.1.6] // Is valid in the query in spite of it is not valid 
                       // (because there is intersection).

And if I discuss more of the situation, I think the request will become more complex.

I wonder if you can help me with the easiest way.

Sincerely.

+5
source share
4 answers

Approach it this way: instead, there is no intersectoral interaction if the validation date is todate <from the date or date of verification fromdate> to date. This assumes check.from <= check.to.

Periods.Any(p => !(check.ToDate < p.FromDate || check.FromDate > p.ToDate));

( ):

Periods.Any(p => check.ToDate >= p.FromDate && check.FromDate <= p.ToDate));
+7

FromDate <= ToDate Period, OverlapsWith :

public static bool OverlapsWith(this Period a, Period b)
{
    return !(b.ToDate <= a.FromDate || a.ToDate <= b.FromDate);
}

, , , a b :

//                         a
//                |-----------------|
//   |--------|                          |-----------|
//       b1                                    b2

. , , , . :

           b.ToDate > a.FromDate && a.ToDate > b.FromDate

LINQ, :

    Periods.Any(period => period.OverlapsWith(periodToCheck))
+6

TimePeriodIntersector.

:

public void TimePeriodIntersectorSample()
{
    TimePeriodCollection periods = new TimePeriodCollection();

    periods.Add( new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 10 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 05 ), new DateTime( 2011, 3, 15 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 12 ), new DateTime( 2011, 3, 18 ) ) );

    periods.Add( new TimeRange( new DateTime( 2011, 3, 20 ), new DateTime( 2011, 3, 24 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 22 ), new DateTime( 2011, 3, 28 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 24 ), new DateTime( 2011, 3, 26 ) ) );

    TimePeriodIntersector<TimeRange> periodIntersector = 
                    new TimePeriodIntersector<TimeRange>();
    ITimePeriodCollection intersectedPeriods = periodIntersector.IntersectPeriods( periods );

    foreach ( ITimePeriod intersectedPeriod in intersectedPeriods )
    {
        Console.WriteLine( "Intersected Period: " + intersectedPeriod );
    }
    // > Intersected Period: 05.03.2011 - 10.03.2011 | 5.00:00
    // > Intersected Period: 12.03.2011 - 15.03.2011 | 3.00:00
    // > Intersected Period: 22.03.2011 - 26.03.2011 | 4.00:00
} // TimePeriodIntersectorSample
+1

Do 2 periods with a common date, say ToDate for period 1 and FromDate of period 2, match, count as at the intersection?

If yes, then a small modification of your request, just to check the dates of the period, if they are within the checked period separately, as if one of the dates fell inside the period, then there is an intersection:

bool conflict = Periods.Any(p => ((p.FromDate >= periodToCheck.fromDate && 
                                    p.ToDate <= periodToCheck.fromDate)
                                  ||
                                   (p.FromDate >= periodToCheck.toDate && 
                                    p.ToDate <= periodToCheck.toDate))
                             );
0
source

All Articles