Check if a date range is within a date range

前端 未结 8 2096
爱一瞬间的悲伤
爱一瞬间的悲伤 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<Membership>
    {
      public int Compare(Membership x, Membership y)
      {
        return x.StartDate.CompareTo(y.StartDate);
      }
    }
    private static bool AddMembership(List<Membership> 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.

    0 讨论(0)
  • 2020-12-09 06:22

    A condition like this should do the trick:

    newItem.StartDate <= range.EndDate && newItem.EndDate.HasValue && newItem.EndDate >= range.StartDate
    
    0 讨论(0)
  • 2020-12-09 06:28

    So if I understand this correctly - you want to make sure date range 2 is not within date range 1?

    For example:

    startDate1 = 01/01/2011
    
    endDate1 = 01/02/2011
    

    and

    startDate2 = 19/01/2011
    
    endDate2 = 10/02/2011
    

    This should be a simple case of:

    if ((startDate2 >= startDate1 &&  startDate2 <= endDate1) || 
        (endDate2   >= startDate1 && endDate2   <= endDate1))
    
    0 讨论(0)
  • 2020-12-09 06:35

    Here's a solution (missing null argument-validation, and validation within Membership that EndDate > StartDate) using Collection<T>:

    public class Membership
    {
        public DateTime StartDate { get; set; }
        public DateTime? EndDate { get; set; } // If null then it lasts forever
    
        private DateTime NullSafeEndDate { get { return EndDate ?? DateTime.MaxValue; } }  
    
        private bool IsFullyAfter(Membership other)
        {
           return StartDate > other.NullSafeEndDate;
        }
    
        public bool Overlaps(Membership other)
        {
          return !IsFullyAfter(other) && !other.IsFullyAfter(this);
        }
    }
    
    
    public class MembershipCollection : Collection<Membership>
    {
       protected override void InsertItem(int index, Membership member)
       {
           if(CanAdd(member))
              base.InsertItem(index, member);
           else throw new ArgumentException("Ranges cannot overlap.");
       }
    
       public bool CanAdd(Membership member) 
       {
           return !this.Any(member.Overlaps);
       }
    }
    
    0 讨论(0)
  • 2020-12-09 06:43

    A bit late but I couldn't find this pattern anywhere in the answers/comments.

        if (startDate1 <= endDate2 && startDate2 <= endDate1)
        {
         // Overlaps.
        }
    
    0 讨论(0)
  • 2020-12-09 06:44
    public bool DoesAnOfferAlreadyExistWithinTheTimeframeProvided(int RetailerId, DateTime ValidFrom, DateTime ValidTo)
            {
                bool result = true;
    
                try
                {
                    // Obtain the current list of coupons associated to the retailer.
                    List<RetailerCoupon> retailerCoupons = PayPalInStore.Data.RetailerCoupon.Find(x => x.RetailerId == RetailerId).ToList();
    
                    // Loop through each coupon and see if the timeframe provided in the NEW coupon doesnt fall between any EZISTING coupon.
                    if (retailerCoupons != null)
                    {
                        foreach (RetailerCoupon coupon in retailerCoupons)
                        {
                            DateTime retailerCouponValidFrom = coupon.DateValidFrom;
                            DateTime retailerCouponValidTo = coupon.DateExpires;
    
                            if ((ValidFrom <= retailerCouponValidFrom && ValidTo <= retailerCouponValidFrom) || (ValidFrom >= retailerCouponValidTo && ValidTo >= retailerCouponValidTo))
                            {
                                return false;
                            }
                        }
                    }
    
                    return result;
                }
            catch (Exception ex)
            {
                this.errorManager.LogError("DoesAnOfferAlreadyExistWithinTheTimeframeProvided failed", ex);
                return result;
            }
        }
    
    0 讨论(0)
提交回复
热议问题