How to gets the number of overlapping days between

2019-06-22 18:39发布

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

标签: c# date range
4条回答
手持菜刀,她持情操
2楼-- · 2019-06-22 19:17

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.

查看更多
Explosion°爆炸
3楼-- · 2019-06-22 19:20

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;
    }
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-06-22 19:22

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;
    }
查看更多
干净又极端
5楼-- · 2019-06-22 19:40

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);
查看更多
登录 后发表回答