几个日期条目之间的间隔
本文关键字:之间 日期 几个 | 更新日期: 2023-09-27 18:08:03
我正在尝试创建一种机制,要求用户输入他们在过去五年中一直在做什么
- 必须涵盖日期范围(开始日期01/08/2009 -结束日期01/08/2014)
- 最多允许10个条目
- 允许重叠
- 不允许有缝隙
目前我按开始日期排序条目,验证两个范围都涵盖了。对于条目i之间的间隔,一次比较两个日期,条目i和i+1,并比较较晚开始日期的开始日期和较早开始日期的结束日期。我发现很难用语言来表达,但我认为这个小图表有助于描述这个问题。
START
A x---------------------------------------y
B x----------y
C x--------y
D x-----y
E x----------y
F x----------y
End
这里选项E会失败,因为它的开始日期在D的结束日期之后,我使用while循环在每天的间隔中添加一天,开始日期在结束日期之后,这将触发验证,即使这些日期已被条目A.I覆盖,我使用Java来做到这一点,但即使在文本和伪代码中提供帮助也会很棒,因为它更多的是我丢失的逻辑,
如果有人能帮我安排一下日期,我将非常感激。
这个逻辑很简单,但是你是反过来看的。
对于请求时间段内的每一天,该日是否被其中一个日期条目所覆盖?如果你发现一天没有被覆盖,那么就有一个缺口,你可以停止检查并将错误发送给用户——除非你想通知用户你发现的所有缺口的细节,否则不要一直检查日期,只要你发现一天没有被覆盖,就"尽早失败"。
那么,在伪代码中…
foreach (Day d in DateRange) {
foreach (UserDateRange u in UserDateRanges) {
//check if the date range (u) covers the day in question (d)
if (d > u.Start && d < u.End) {
//we're done checking this day because it's covered by at least one range
covered = true;
}
}
if (!covered) return false;
}
return true; //because if we got this far, every day is "covered"
所以…它循环遍历日期,对于每一天,它检查所有日期范围。如果找到一个可以覆盖一天,那么你可以去第二天。
这里有很多优化的空间。例如,当您找到涵盖一天的日期范围时,您可以跳到该日期范围的末尾,而不需要检查该范围中的其余日期。复杂条件下的FOR循环可以在这里工作。你知道你可以在里面放任何你想要的条件,对吧?
for (int x = 0; covered == false; x++ ) //perfectly valid
我是这样做的…创建一个可以保存所有时间范围合并的数组。把所有的日期过一遍,写在单子上。检查列表中的空白。我相信有更好的方法……但就你现在所做的来说,这就足够了。当然在吹代码中有bug…但这是一个很好的开始。顺便说一句,这些都在c#中。
int startYear = 2000;
int endYear = 2005;
void Main()
{
int totalDays = Convert.ToInt32((new DateTime(endYear, 12, 31) - (new DateTime(startYear, 01, 01))).TotalDays);
bool[] days = new bool[totalDays];
List<Tuple<DateTime, DateTime>> times = new List<Tuple<DateTime, DateTime>>() {
new Tuple<DateTime, DateTime>(new DateTime(2000, 01, 01), new DateTime(2000, 01, 05)),
new Tuple<DateTime, DateTime>(new DateTime(2000, 01, 08), new DateTime(2002, 06, 15)),
new Tuple<DateTime, DateTime>(new DateTime(2002, 06, 19), new DateTime(2005, 12, 26))
};
// Go over all blocks and add them to the days array. This could be bit logic if you really want to save memory
foreach(Tuple<DateTime, DateTime> block in times) {
int startBlock = GetBlockFromDate(block.Item1);
int endBlock = GetBlockFromDate(block.Item2);
for(int blockIndex = startBlock; blockIndex < endBlock; blockIndex++) {
days[blockIndex] = true;
}
}
// this is the actual checking for gaps... I chose to use a linear approach.
for (int dayIndex = 0; dayIndex < days.Length; dayIndex++) {
if (!days[dayIndex]) {
DateTime missingDate = new DateTime(startYear, 1, 1).AddDays(dayIndex);
Console.WriteLine("Missing Day: {0}", missingDate);
}
}
}
int GetBlockFromDate(DateTime blockDate) {
DateTime startDate = new DateTime(startYear, 1, 1);
int blockIndex = Convert.ToInt32((blockDate - startDate).TotalDays);
return blockIndex;
}
输出:Missing Day: 1/5/2000 12:00:00 AM
Missing Day: 1/6/2000 12:00:00 AM
Missing Day: 1/7/2000 12:00:00 AM
Missing Day: 6/15/2002 12:00:00 AM
Missing Day: 6/16/2002 12:00:00 AM
Missing Day: 6/17/2002 12:00:00 AM
Missing Day: 6/18/2002 12:00:00 AM
Missing Day: 12/26/2005 12:00:00 AM
Missing Day: 12/27/2005 12:00:00 AM
Missing Day: 12/28/2005 12:00:00 AM
Missing Day: 12/29/2005 12:00:00 AM
Missing Day: 12/30/2005 12:00:00 AM
如果您有一个有序的日期范围列表。在伪代码中,因为您似乎不知道要使用哪种语言。
end = 31/12/2008
foreach(DateRange d in ranges)
{
if d.end >= end
{
if d.start <= end + 1
end = d.end
else
// Gap found (end + 1 to d.start - 1)
//break , return error?
// or if you wanted to identify the all the gaps, perhaps
// gaps.add(new DateRange(end +1, d.start - 1))
// end = d.end
}
}
当然没有必要每次增加一天。