多个日期条目之间的锻炼差距

时间:2014-06-09 22:29:13

标签: java c# date calendar logic

我正在尝试创建一种机制,要求用户输入他们过去五年来所做的事情

  • 必须涵盖日期范围(开始日期01/08/2009 - 结束日期01/08/2014)
  • 最多允许十个条目
  • 允许重叠
  • 不允许有间隙

目前我按开始日期订购条目,验证两个范围都已涵盖。对于条目之间的差距,我一次比较两个日期,条目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循环为每天的间隙添加一天开始日期是在结束日期之后,这将触发验证,即使那些日期已被条目所涵盖我正在使用Java来执行此操作,但即使是文本和伪代码的帮助也会很棒,因为它更多的是逻辑错误,

如果有人能帮助解决日期之间的差距,我将非常感激。

3 个答案:

答案 0 :(得分:1)

这个逻辑很简单,但是你要向后看它。

对于所请求时间段内的每一天,该日期是否包含在其中一个日期条目中?如果您发现某一天未被覆盖,则会出现间隙,您可以停止检查并将错误发回给用户 - 除非您要通知用户,否则请不要检查日期你所识别的所有差距的细节,只是"早期失败"一旦你找到一个没有覆盖的日子。

所以,在伪代码......

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

答案 1 :(得分:1)

以下是我将如何去做...创建一个可以保存所有时间范围合并的数组。浏览所有日期并将其放入列表中。检查列表中的差距。我相信有更好的方法......但是对于你正在做的事情,这样做会很好。当然,吹码中有漏洞......但它是一个很好的开始。多数都是在C#btw。

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

答案 2 :(得分:1)

如果您有一个有序的日期范围列表。 在伪代码中看到,因为您似乎不知道您将使用哪种语言。

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
   }
}

当然不需要一次添加1天。