我正在努力使自己转过头来。
我有一个List<Appointment>
,其中包含DateTime Start
和DateTime End
以及其他一些位。
我想画一个日程安排者,其中列出所有约会,并在适当的地方按占位符/空白排列。
我已经解决了这个问题,但是现在我需要处理约会重叠的情况。看来可能是这样;
这感觉像是一个必须先解决的问题。有指针吗?
这是我目前正在处理的一些可怕代码的示例;
List<TechActivityModel> techActivity = new TechService().GetTechActivity(7, new DateTime(2018, 4, 11), new DateTime(2018, 4, 11).AddDays(1))
.OrderBy(t => t.Start).ToList();
for (int i = techActivity.Count - 1; i >= 0; i--)
{
//something starts before and ends after
TechActivityModel clash = techActivity.Where(t => t.Id != techActivity[i].Id && t.Start < techActivity[i].Start && t.End > techActivity[i].End).FirstOrDefault();
while (clash != null)
{
//split the clashing activity into a task before and another task after the existing on
//first create the 2nd part of the task (after the existing one)
TechActivityModel activityContinued = new TechActivityModel()
{
Start = techActivity[i].End,
End = clash.End,
Subject = "++" + clash.Subject
};
activityContinued.Length = (int)(activityContinued.End - activityContinued.Start).TotalMinutes;
techActivity.Add(activityContinued);
//update the clashing task to finish when the existing task starts
clash.Subject = "+" + clash.Subject;
clash.End = techActivity[i].Start;
clash.Length = (int)(clash.End - clash.Start).TotalMinutes;
clash = techActivity.Where(t => t.Id != techActivity[i].Id && t.Start < techActivity[i].Start && t.End > techActivity[i].End).FirstOrDefault();
}
}
for (int i = techActivity.Count - 1; i >= 0; i--)
{
//something starts before and ends during
TechActivityModel clash = techActivity.Where(t => t.Id != techActivity[i].Id && t.Start <= techActivity[i].Start && t.End > techActivity[i].Start).FirstOrDefault();
while (clash != null)
{
//update the clashing task to finish when the existing task starts
clash.Subject = "/" + clash.Subject;
clash.End = techActivity[i].Start;
clash.Length = (int)(clash.End - clash.Start).TotalMinutes;
clash = techActivity.Where(t => t.Id != techActivity[i].Id && t.Start < techActivity[i].Start && t.End > techActivity[i].Start).FirstOrDefault();
}
}
techActivity = techActivity.OrderBy(t => t.Start).ToList();
//now we're going to pad all the gaps
List<TechActivityModel> newList = new List<TechActivityModel>();
DateTime LastEnd = techActivity[0].End;
//start with the gap from midnight till the first task
newList.Add(new TechActivityModel()
{
Start = new DateTime(2018, 4, 10),
End = techActivity[0].Start,
TicketNumber = 0,
Note = "",
TicketSubject = "",
TimeLogged = 0,
Id = 0
}
);
//pad all the gaps
for (int i = 1; i < techActivity.Count; i++)
{
if (LastEnd < techActivity[i].Start.AddMinutes(-2))
{
TechActivityModel gap = new TechActivityModel()
{
Start = LastEnd.AddMinutes(1),
End = techActivity[i].Start,
Subject = "",
Id = 0
};
gap.Length = (int)(gap.End - gap.Start).TotalMinutes;
newList.Add(gap);
}
LastEnd = techActivity[i].End;
}
//and finally fill the gap from the last task till midnight
newList.Add(new TechActivityModel()
{
Start = LastEnd,
End = new DateTime(2018, 4, 11),
Subject = "",
Length = 0
}
);
newList.AddRange(techActivity);
string content = "";
foreach (TechActivityModel techActivityModel in newList.OrderBy(t => t.Start))
{
content +=
techActivityModel.Start.ToShortTimeString()
+ " - " + techActivityModel.End.ToShortTimeString()
+ " (" + techActivityModel.Length + "mins)"
+ " : " + techActivityModel.Subject
+ Environment.NewLine;
}
答案 0 :(得分:1)
如果我对您的理解正确,那么这就是我如何解决您的问题。我将从在一个列表中一起找到所有不同的Start
和End
值开始。我们希望它们与众不同且井井有条。然后,我们将列表与自身压缩在一起以生成对:
var l = new List<Appointment>();
var ex = l.SelectMany(a => new[] { a.Start, a.End }).Distinct().OrderBy(dt => dt);
var pairs = ex.Zip(ex.Skip(1), (First, Second) => new { First, Second });
现在,使用我在评论中提到的规则:
如果时段
a
在时段b
之前开始并且时段b
在时段a
之前开始,则两个时间段重叠。
我们遍历每对日期时间,然后在约会列表中重新查询与该对描述的时间段重叠的所有所有约会。如果没有结果,则该时间段当前是免费的。如果得到一个结果,则您(在此期间)的约会没有其他任何重叠。如果得到多个结果,则说明冲突,并且可以计算出显示方式。但是请注意,您不必在这个时间段内再次访问 并延长/缩短它,更新其文本等。