How to gets the number of overlapping days between

2019-06-22 18:55发布

问题:

let me explain the situation first - let's say i have 4 dates: BS, BE, PS, PE (S for start, E for end). I need to know how many days are over lapping when given those dates. for example : BE-05.01 , BS-10.01, PS-03.01, PE-07.01 the result is: 3 (05.01, 06.01 and 07.01 are overlapping)

I wrote the following code but it seems to messy and i want to check if maybe there is a simpler way to do this:

private static double GetNumOfOverLappingDays(DateTime BS, DateTime BE, DateTime PS, DateTime PE)
    {
        //case 1:
        //                  |--- B ---|
        //                  |----P ---|

        //case 2:
        //                  |--- B ---|
        //                          | --- P --- |

        //case 3:
        //                  |--- B ---|
        //          | --- P ---- |

        //case 4:
        //                  |--- B ---|
        //                     | - P - |

        //case 5:
        //                  |--- B ---|
        //              | -------- P -------- |

        double days = -1;
        bool isNotOverLap = (BS > PE) || (PS > BE);

        if (isNotOverLap == false)
        {
            //case 1
            if (BS == PS && BS == PE)
            {
                days = (PE - PS).TotalDays;
            }
            //case 2
            else if (BE > PS && BE < PE)
            {
                days = (BE - PS).TotalDays;
            }
            //case 3
            else if (BS > PS && BS < PE)
            {
                days = (PE - BS).TotalDays;
            }
            //case 4
            else if (BS < PS && BE > PE)
            {
                days = (PE - PS).TotalDays;
            }
            //case 5
            else if (BS > PS && BE < PE)
            {
                days = (BE - PS).TotalDays;
            }
        }
        return days+1;
    }

thanks in advance for any assitance,

Amit

回答1:

Try this:

    private static double GetOverlappingDays(DateTime firstStart, DateTime firstEnd, DateTime secondStart, DateTime secondEnd)
    {
        DateTime maxStart = firstStart > secondStart ? firstStart : secondStart;
        DateTime minEnd = firstEnd < secondEnd ? firstEnd : secondEnd;
        TimeSpan interval = minEnd - maxStart;
        double returnValue = interval > TimeSpan.FromSeconds(0) ? interval.TotalDays : 0;
        return returnValue;
    }


回答2:

Try to use for loop:

DateTime d1 = new DateTime(2013,12,1),
            d2 = new DateTime(2013,12,14),
            d3 = new DateTime(2013,12,10),
            d4 = new DateTime(2013,12,20);
int count = 0;

for (var d = d1.Date; d <= d2.Date; d = d.AddDays(1))
{
      if (d >= d3.Date && d <= d4.Date)
           count++;
}

Console.WriteLine(count);

Notice that this code gives integer value. If you need value in hours this code will not fit. Also this is not the most efficient approach, but it's simple and works ok for small ranges.



回答3:

If you have two strongly related values, like start and end date, then it's good idea to have object which will hold them both. Consider creating DateRange class:

public class DateRange
{
    public DateRange(DateTime start, DateTime end)
    {
        if (start > end) throw new ArgumentException();

        Start = start;
        End = end;
    }

    public DateTime Start { get; private set; }
    public DateTime End { get; private set; }
    public double TotalDays { get { return (End - Start).TotalDays; } }

    public bool Includes(DateTime value)
    {
        return (Start <= value) && (value <= End);
    }

    public DateRange Intersect(DateRange range)
    {
        if (range.Includes(Start))
            return new DateRange(Start, (End < range.End) ? End : range.End);

        if (range.Includes(End))
            return new DateRange(range.Start, End);

        if (Start < range.Start && range.End < End)
            return range;

        return null;
    }
}

Usage:

public static double GetNumOfOverLappingDays(DateRange b, DateRange p)
{
   DateRange overlap = b.Intersect(p);
   if (overlap == null)
       return 0;

   return overlap.TotalDays;
}

Create date ranges and pass them to this method:

var b = new DateRange(new DateTime(2013, 12, 20), new DateTime(2013, 12, 25));
var p = new DateRange(new DateTime(2013, 12, 22), new DateTime(2013, 12, 26)); 
double totalDays = GetNumOfOverLappingDays(b, p);


回答4:

I would propose to calculate the latest start and earliest end and then subtract the two. Note that this example can return negative numbers if the time is not overlapping at all, but this was not one of the 5 cases you mentioned.

    static void Main(string[] args)
    {
        DateTime start1 = new DateTime(2013,1,2);
        DateTime end1 = new DateTime(2013,1,14);

        DateTime start2 = new DateTime(2013,1,1);
        DateTime end2 = new DateTime(2013,1,12);

        DateTime lateStart = GetLatest(start1, start2);
        DateTime earlyEnd = GetEarliest(end1, end2);

        Console.WriteLine((earlyEnd-lateStart).TotalDays + 1);
        Console.ReadLine();
    }

    private static DateTime GetEarliest(DateTime start1, DateTime start2)
    {
        return start1 < start2 ? start1 : start2;
    }

    private static DateTime GetLatest(DateTime start1, DateTime start2)
    {
        return start1 > start2 ? start1 : start2;
    }


标签: c# date range