Check if a date range is within a date range

前端 未结 8 2124
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-09 06:01

I have the following class:

public class Membership
{
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; } // If null then          


        
8条回答
  •  忘掉有多难
    2020-12-09 06:21

    If you don't have different criteria for sorting, then start by maintaining your list in order. Since no previously-added object is allowed to overlap, then once you know the point where you would add a new object you need only compare the single objects at either side to be sure the new object is allowed. You also only need to consider whether the end date of the "earlier" object is overlaps with the start date of the "later" object, as this ordering makes the other possibility for an overlap irrelevant.

    Hence as well as simplifying the question of detecting overlaps, we can reduce the complexity from O(n) of to O(log n), as rather than compare with all existing items, we compare with 0-2 we've found through an O(log n) search.

    private class MembershipComparer : IComparer
    {
      public int Compare(Membership x, Membership y)
      {
        return x.StartDate.CompareTo(y.StartDate);
      }
    }
    private static bool AddMembership(List lst, Membership ms)
    {
      int bsr = lst.BinarySearch(ms, new MembershipComparer());
      if(bsr >= 0)    //existing object has precisely the same StartDate and hence overlaps
                      //(you may or may not want to consider the case of a zero-second date range)
        return false;
      int idx = ~bsr; //index to insert at if doesn't match already.
      if(idx != 0)
      {
        Membership prev = lst[idx - 1];
        // if inclusive ranges is allowed (previous end precisely the same
        // as next start, change this line to:
        // if(!prev.EndDate.HasValue || prev.EndDate > ms.StartDate)
        if(prev.EndDate ?? DateTime.MaxValue >= ms.StartDate)
          return false;
      }
      if(idx != lst.Count)
      {
        Membership next = lst[idx];
        // if inclusive range is allowed, change to:
        // if(!ms.EndDate.HasValue || ms.EndDate > next.StartDate)
        if(ms.EndDate ?? DateTime.MaxValue >= next.StartDate)
          return false;
      }
      lst.Insert(idx, ms);
      return true;
    }
    

    The above returns false if it was unable to add to the list. If it would be more appropriate to throw an exception, this is an easy modification.

提交回复
热议问题