C# 检查日期范围是否在日期范围内
我有以下课程:C# 检查日期范围是否在日期范围内,c#,C#,我有以下课程: public class Membership { public DateTime StartDate { get; set; } public DateTime? EndDate { get; set; } // If null then it lasts forever } 我需要确保添加到以下列表时,新项目不会与现有项目的日期重叠: var membership = new List<Membership> { new Membersh
public class Membership
{
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; } // If null then it lasts forever
}
我需要确保添加到以下列表时,新项目不会与现有项目的日期重叠:
var membership = new List<Membership>
{
new Membership { StartDate = DateTime.UtcNow.AddDays(-10), EndDate = DateTime.UtcNow.AddDays(-5) },
new Membership { StartDate = DateTime.UtcNow.AddDays(-5), EndDate = null }
};
我原以为这很简单,但到目前为止,我的尝试都是错误的,我开始困惑自己,希望有人做了类似的事情,他们可以分享。谢谢像这样的情况应该会奏效:
newItem.StartDate <= range.EndDate && newItem.EndDate.HasValue && newItem.EndDate >= range.StartDate
newItem.StartDate=range.StartDate
如果我理解正确-您想确保日期范围2不在日期范围1内吗
例如:
startDate1 = 01/01/2011
endDate1 = 01/02/2011
及
这应该是一个简单的例子:
if ((startDate2 >= startDate1 && startDate2 <= endDate1) ||
(endDate2 >= startDate1 && endDate2 <= endDate1))
如果((startDate2>=startDate1&&startDate2=startDate1&&endDate2)基本上,一个日期范围与另一个日期范围重叠,如果其任何结尾在另一个范围内,则反之亦然
static bool AllowedToAdd(List<Membership> membershipList, Membership newItem)
{
return !membershipList.Any(m =>
(m.StartDate < newItem.StartDate &&
newItem.StartDate < (m.EndDate ?? DateTime.MaxValue))
||
(m.StartDate < (newItem.EndDate ?? DateTime.MaxValue) &&
(newItem.EndDate ?? DateTime.MaxValue) <= (m.EndDate ?? DateTime.MaxValue))
||
(newItem.StartDate < m.StartDate &&
m.StartDate < (newItem.EndDate ?? DateTime.MaxValue))
||
(newItem.StartDate < (m.EndDate ?? DateTime.MaxValue) &&
(m.EndDate ?? DateTime.MaxValue) <= (newItem.EndDate ?? DateTime.MaxValue))
);
}
下面是一个使用集合的解决方案(缺少null
参数验证,以及Membership
中的验证,即EndDate>StartDate
):
公共类成员资格
{
公共日期时间起始日期{get;set;}
public DateTime?EndDate{get;set;}//如果为空,则它将永远持续
私有DateTime NullSafeEndDate{get{return EndDate??DateTime.MaxValue;}}
private bool IsFullyAfter(其他会员资格)
{
返回StartDate>other.NullSafeEndDate;
}
公共布尔重叠(其他成员)
{
return!IsFullyAfter(其他)和&!other.IsFullyAfter(此);
}
}
公共类成员身份集合:集合
{
受保护的重写void插入项(int索引,成员资格成员)
{
if(加拿大(成员))
基本插入项(索引,成员);
else抛出新的ArgumentException(“范围不能重叠”);
}
公共bool CanAdd(会员)
{
return!this.Any(member.Overlaps);
}
}
< /代码> 如果你没有不同的排序标准,那么先按顺序维护你的列表。因为没有以前添加的对象被允许重叠,所以一旦你知道你要添加一个新对象的点,你只需要比较两边的单个对象就可以确定新的对象。你也只需要考虑。“较早”对象的结束日期是否与“较晚”对象的开始日期重叠,因为此顺序使得重叠的其他可能性无关
因此,除了简化检测重叠的问题外,我们还可以将复杂性从O(n)of降低到O(logn),而不是与所有现有项进行比较,而是与通过O(logn)搜索找到的0-2进行比较
私有类成员身份比较程序:IComparer
{
公共整数比较(成员x、成员y)
{
返回x.StartDate.CompareTo(y.StartDate);
}
}
私有静态bool AddMembership(列表lst、成员ms)
{
int bsr=lst.BinarySearch(ms,newmembershipComparer());
if(bsr>=0)//现有对象具有完全相同的起始日期,因此重叠
//(您可能或可能不想考虑零秒日期范围的情况)
返回false;
int idx=~bsr;//要在if处插入的索引不匹配。
如果(idx!=0)
{
成员资格prev=lst[idx-1];
//如果允许包含范围(前一个端点完全相同
//作为下一个开始,将此行更改为:
//如果(!prev.EndDate.HasValue | | prev.EndDate>ms.StartDate)
如果(prev.EndDate??DateTime.MaxValue>=ms.StartDate)
返回false;
}
如果(idx!=1次计数)
{
下一个成员=lst[idx];
//如果允许包含范围,请更改为:
//如果(!ms.EndDate.HasValue | | ms.EndDate>next.StartDate)
如果(ms.EndDate??DateTime.MaxValue>=next.StartDate)
返回false;
}
第一次插入(idx,ms);
返回true;
}
如果无法添加到列表中,则上述返回false
。如果更适合引发异常,则这是一个简单的修改。public bool在提供的时间范围内不提供ReadyExistin(int RetailerId、DateTime ValidFrom、DateTime ValidTo)
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;
}
}
{
布尔结果=真;
尝试
{
//获取与零售商关联的优惠券的当前列表。
List retailerCoupons=PayPalInStore.Data.RetailerCoupon.Find(x=>x.RetailerId==RetailerId.ToList();
//循环浏览每一张优惠券,看看新优惠券中提供的时间范围是否在任何现有优惠券之间。
if(零售组!=null)
{
foreach(零售团体中的零售团体优惠券)
{
DateTime RetailerGrouponValidFrom=优惠券。DateValidFrom;
DateTime RetailerGrouponValidTo=优惠券。DateExpires;
如果((ValidFrom=RetailerGrouponValidTo))
{
返回false;
}
}
}
返回结果;
}
捕获(例外情况除外)
{
this.errorManager.LogError(“DoesanOfferReadyExistwithinthetimeframesfiled failed”,ex);
返回结果;
}
}
有点晚了,但我在答案/评论中找不到这种模式
if (startDate1 <= endDate2 && startDate2 <= endDate1)
{
// Overlaps.
}
if(startDate1我想出了以下方法来检查日期是否重叠,这可能不是最有效的方法,但我希望这能有所帮助
public static bool DateRangesOverlap(DateTime startDateA, DateTime endDateA, DateTime startDateB, DateTime endDateB)
{
var allDatesA = new List<DateTime>();
var allDatesB = new List<DateTime>();
for (DateTime date = startDateA; date <= endDateA; date = date.AddDays(1))
{
allDatesA.Add(date);
}
for (DateTime date = startDateB; date <= endDateB; date = date.AddDays(1))
{
allDatesB.Add(date);
}
var isInRange = false;
foreach (var date in allDatesA)
{
var existsInAllDatesB = allDatesB.Any(x => x == date);
if (existsInAllDatesB)
{
isInRange = true;
break;
}
}
return isInRange;
}
public static bool DateRangesOverlap(DateTime startDateA、DateTime endDateA、DateTime startDateB、DateTime endDateB)
{
var allDatesA=新列表();
var allDatesB=新列表();
对于(DateTime date=startDateA;date),您还应该检查空值。感谢所有人的回复,但我更喜欢这个,因为它是最容易理解的lol。这是一个非常符合逻辑的天才解决方案。Thnx@Joachim VR
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);
}
}
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;
}
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;
}
}
if (startDate1 <= endDate2 && startDate2 <= endDate1)
{
// Overlaps.
}
public static bool DateRangesOverlap(DateTime startDateA, DateTime endDateA, DateTime startDateB, DateTime endDateB)
{
var allDatesA = new List<DateTime>();
var allDatesB = new List<DateTime>();
for (DateTime date = startDateA; date <= endDateA; date = date.AddDays(1))
{
allDatesA.Add(date);
}
for (DateTime date = startDateB; date <= endDateB; date = date.AddDays(1))
{
allDatesB.Add(date);
}
var isInRange = false;
foreach (var date in allDatesA)
{
var existsInAllDatesB = allDatesB.Any(x => x == date);
if (existsInAllDatesB)
{
isInRange = true;
break;
}
}
return isInRange;
}