我正在做一个个人项目,只返回我拥有的可用插槽。 我有两个列表,一个带有所有可能的日期时间槽,另一个带有所有阻止日期时间的列表。
现在我有以下代码,但是正在返回重叠的记录(这与我想要的相反)
那么,我做错了什么,最好的方法是什么?
(我搜索并且找不到与非重叠日期时间有关的任何内容)
结果应该是这样的:
2018-09-02 01:30:00
班级DateSpan { 公共DateTime StartDate; 公共DateTime EndDate;
public DateSpan(DateTime start, DateTime end)
{
StartDate = start;
EndDate = end;
}
public DateSpan(DateTime start, int duration)
{
StartDate = start;
EndDate = start.AddHours(duration);
}
public static void Main(string[] args)
{
var AvailableHours = new System.Collections.Generic.List<DateSpan>();
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 1, 5, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 4, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 5, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 1, 30, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 4, 5, 0, 0), 2));
var BlockTimes = new System.Collections.Generic.List<DateSpan>();
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 1, 10, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 2, 5, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 3, 5, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 4, 4, 0, 0), 2));
var e = AvailableHours.SelectMany((DateSpan x) =>
{
var result = new List<DateSpan>();
foreach (var o in BlockTimes.Where(y => x.StartDate < y.StartDate && y.StartDate < x.EndDate).ToList())
{
result.Add(new DateSpan(new DateTime(Math.Max(x.StartDate.Ticks, o.StartDate.Ticks)), new DateTime(Math.Min(x.EndDate.Ticks, o.EndDate.Ticks))));
}
return result;
});
}
}
答案 0 :(得分:0)
根据对您问题的澄清,这似乎可以解决问题。它使用foreach循环而不是直接的Linq,但是对我来说,这使代码更具可读性,并且解决方案更简单:
private List<DateSpan> GetNonOverlappingTimes()
{
var AvailableHours = new System.Collections.Generic.List<DateSpan>();
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 1, 5, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 4, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 5, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 1, 30, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 4, 5, 0, 0), 2));
var BlockTimes = new System.Collections.Generic.List<DateSpan>();
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 1, 10, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 2, 5, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 3, 5, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 4, 4, 0, 0), 2));
var availableTimes = new List<DateSpan>();
foreach (var avail in AvailableHours)
{
// check if there are any block times where the start date or end date is between the start date and end date of the available time
bool isConflict = BlockTimes.Exists(bt => (bt.StartDate >= avail.StartDate && bt.StartDate < avail.EndDate) || (bt.EndDate > avail.StartDate && bt.EndDate <= avail.EndDate));
if (!isConflict)
availableTimes.Add(avail);
}
return availableTimes;
}
这给出了您期望的结果。
答案 1 :(得分:0)
在DateSpan
类中定义一个方法,该方法将知道如何确定两个日期跨度是否相交:
public bool Intersect(DateSpan other)
{
return (this.StartDate >= other.StartDate && this.StartDate <= other.EndDate) ||
(this.EndDate >= other.StartDate && this.EndDate <= other.EndDate);
}
然后,使用此方法发现可用的时隙:
private List<DateSpan> GetNonOverlappingTimes()
{
var AvailableHours = new System.Collections.Generic.List<DateSpan>();
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 1, 5, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 4, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 5, 0, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 2, 1, 30, 0), 2));
AvailableHours.Add(new DateSpan(new DateTime(2018, 9, 4, 5, 0, 0), 2));
var BlockTimes = new System.Collections.Generic.List<DateSpan>();
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 1, 10, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 2, 5, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 3, 5, 0, 0), 2));
BlockTimes.Add(new DateSpan(new DateTime(2018, 9, 4, 4, 0, 0), 2));
return AvailableHours.Where(x => BlockTimes.All(y => !x.Intersect(y))).ToList();
}