【问题标题】:Check if two dates overlap in any possible way检查两个日期是否以任何可能的方式重叠
【发布时间】:2017-02-28 11:42:42
【问题描述】:

我需要检查 DateTime-span 是否与任何现有的时间块重叠。

我的函数应该检查是否有任何重叠 并且将运行数百次,新的开始和结束日期之间的时间跨度为 10 分钟。 现有时间块的跨度可能是 5-60 分钟长。

收到的第一个 span 始终是最早的日期,收到的最后一个 span 始终是最晚的日期。 existingTimeBlocks 列表也按 StartDate 排序

    private bool TimeBlockIsOverLapping(DateTime newTimeBlockStart, DateTime newTimeBlockEnd, IEnumerable<TimeBlock> existingTimeBlocks)
    {
        // The new TimeBlock starts later than latest existing TimeBlock or ends earlier that first existing timeblock so it won't overlap
        if (existingTimeBlocks.Count() == 0)
        {
            return false;
        }

        // The new TimeBlock is within the scope of old TimeBlocks and might overlap
        else
        {
            // TODO: Insert overlap checks here
        }
    }

编辑:TimeBlock 的简化定义:

public class TimeBlock
    {
        [Required]
        public int Id { get; set; }

        [Required]
        public DateTime StartTime { get; set; }

        [Required]
        public DateTime EndTime { get; set; }

        [Required]
        public int ScheduleId { get; set; }

        [Required]
        public virtual Schedule Schedule { get; set; }
    }

编辑:进一步澄清: existingTimeBlocks 可以是例如每周一和周四的 9:00 - 12:00 和 13:00-16:00 共 6 周,因此可以在周一的 12:00 和 13:00 之间传递 60 分钟的 timeSpan 和有效

【问题讨论】:

  • existingTimeBlocks.Count() 你不应该……接受IEnumerable的方法的第一条规则是只枚举一次。
  • 它看起来像一个家庭任务。你尝试过什么吗?没有人会为你做你的工作。
  • 请问可以添加TimeBlock的定义吗?
  • @RobLang 根据最后一段问题,它可能包括 StartDate 和 EndDate ;)
  • 要指定的一件重要事情是您的时间范围是关闭的还是半开放的。对于这些事情,通常使用半开间隔,其中开始时间包含在范围内,但结束时间不包含在范围内。这使您可以(例如)更轻松地表示整个小时,而不会意外地在两个不同范围内包含一个精确小时的时间。

标签: c#


【解决方案1】:

类似:

private static bool TimeBlockIsOverLapping(DateTime newTimeBlockStart, DateTime newTimeBlockEnd, IEnumerable<TimeBlock> existingTimeBlocks) {
    foreach (var block in existingTimeBlocks) {
        // This is only if existingTimeBlocks are ordered. It is only
        // a speedup
        if (newTimeBlockStart > block.EndTime) {
            break;
        }

        // This is the real check. The ordering of the existingTimeBlocks
        // is irrelevant
        if (newTimeBlockStart <= block.EndTime && newTimeBlockEnd >= block.StartTime) {
            return true;
        }
    }

    return false;
}

为了检查重叠块,我使用了Algorithm to detect overlapping periods

【讨论】:

  • 请注意,此解决方案假定一个封闭区间。这意味着时间范围 10:00-11:00 和时间范围 11:00-12:00 将重叠。 (出于这个原因,我避免关闭时间间隔,但 OP 需要决定这一点。)
  • 时间范围10:00-11:00和11:00-12:00应该可以通过检查
【解决方案2】:

好吧,让我们来实现:

// static: we don't want "this" in the context
private static bool TimeBlockIsOverLapping(DateTime newTimeBlockStart, 
                                           DateTime newTimeBlockEnd, 
                                           IEnumerable<TimeBlock> existingTimeBlocks) {
  if (null == existingTimeBlocks)
    return false;
  else if (newTimeBlockStart > newTimeBlockEnd)
    return false;

  // assuming that there' no null blocks within existingTimeBlocks
  // and all blocks within existingTimeBlocks are valid ones
  foreach (var block in existingTimeBlocks) {
    //TODO: check edges: < or <=; > or >=
    if ((newTimeBlockStart < block.EndTime) && (newTimeBlockEnd > block.StartTime))
      return true; // overlap found
  }  

  return false; // no overlap found  
}

【讨论】:

  • 如果愿意,方法的后半部分也可以写成/* TODO: check edges: &lt; or &lt;=; &gt; or &gt;= */ return existingTimeBlocks.Any(block =&gt; (newTimeBlockStart &lt; block.EndTime) &amp;&amp; (newTimeBlockEnd &gt; block.StartTime));
【解决方案3】:

假设您的时间块包含开始日期和结束日期,请使用 OverlapsWith 函数...

public class TimeBlock
{
    public DateTime EndTime {get;set;}
    public DateTime StartTime {get;set;}

    public bool OverlapsWith(TimeBlock other)
    {
        return (StartTime <= other.StartTime && EndTime >= other.StartTime)
            || (StartTime <= other.EndTime && EndTime >= other.EndTime);
    }
}

然后在你的函数中......

var myBlock = new TimeBlock{ EndTime = newTimeBlockEnd, StartTime = newTimeBlockStart};
if(existingTimeBlocks.Any(x => x.OverlapsWith(myBlock)))
   // ...your code

【讨论】:

  • 此方案的优点是“OOP-thinking”(TimeBlock 类中的 TimeBlock 比较逻辑,而不是 helper 方法)和现有 Linq 方法的使用。目前不是 +1,因为 OverlapsWith 并未涵盖所有情况(请参阅 xanatos 链接的帖子:stackoverflow.com/questions/13513932/…
猜你喜欢
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多