【问题标题】:Workout Gaps between several date entries几个日期条目之间的锻炼间隔
【发布时间】:2014-07-30 13:40:37
【问题描述】:

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

  • 必须涵盖日期范围(开始日期 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 循环在每天的间隙中添加一天,开始日期在结束日期之后,这将触发验证,即使那些日期已被条目覆盖 AI 正在使用 Java 来执行此操作,但即使是文本和伪代码的帮助也会很棒,因为它更多的是我丢失的逻辑,

如果有人可以帮助解决日期之间的差距,我将不胜感激。

【问题讨论】:

  • 只需将所有条目折叠到一个时间线并使用二进制搜索来查找间隙。分辨率是多少?就几天? 1825 位?

标签: java c# date calendar logic


【解决方案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 天。

【讨论】:

    【解决方案2】:

    这就是我将如何去做...创建一个可以合并所有时间范围的数组。查看所有日期并将它们放入列表中。检查列表中的空白。我相信有更好的方法......但是对于你正在做的事情,这会很好。当然,打击代码中存在错误......但它是一个很好的开始。顺便说一句,这就是 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
    

    【讨论】:

      【解决方案3】:

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

      对于请求时间段内的每一天,该日期是否包含在其中一个日期条目中?如果您发现未涵盖的日期,则存在间隙,您可以停止检查并将错误发送回用户 - 不要继续检查日期,除非您想通知用户您识别的所有间隙的细节,只要找到未涵盖的日期,就“尽早失败”。

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

      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
      

      【讨论】:

      • Jasmine 这对您有很大帮助,感谢您的详细回复。我没有使用确切的解决方案,而是使用了类似的想法,您对我倒退的想法是正确的。谢谢马蒂
      猜你喜欢
      • 1970-01-01
      • 2015-08-06
      • 2022-09-27
      • 2017-04-26
      • 2013-08-28
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多