2010-04-20 165 views
9

基本上我只想检查一个时间段是否与另一个时间段重叠。 空结束日期意味着无穷大。任何人都可以缩短这一点,因为它有时很难阅读。干杯任何人都可以为我简化这个算法吗?

public class TimePeriod 
    { 
     public DateTime StartDate { get; set; } 
     public DateTime? EndDate { get; set; } 

     public bool Overlaps(TimePeriod other) 
     { 
      // Means it overlaps 
      if (other.StartDate == this.StartDate 
       || other.EndDate == this.StartDate 
       || other.StartDate == this.EndDate 
       || other.EndDate == this.EndDate) 
       return true; 

      if(this.StartDate > other.StartDate) 
      { 
       // Negative 
       if (this.EndDate.HasValue) 
       { 
        if (this.EndDate.Value < other.StartDate) 
         return true; 
        if (other.EndDate.HasValue && this.EndDate.Value < other.EndDate.Value) 
         return true; 
       } 

       // Negative 
       if (other.EndDate.HasValue) 
       { 
        if (other.EndDate.Value > this.StartDate) 
         return true; 
        if (this.EndDate.HasValue && other.EndDate.Value > this.EndDate.Value) 
         return true; 
       } 
       else 
        return true; 
      } 
      else if(this.StartDate < other.StartDate) 
      { 
       // Negative 
       if (this.EndDate.HasValue) 
       { 
        if (this.EndDate.Value > other.StartDate) 
         return true; 
        if (other.EndDate.HasValue && this.EndDate.Value > other.EndDate.Value) 
         return true; 
       } 
       else 
        return true; 

       // Negative 
       if (other.EndDate.HasValue) 
       { 
        if (other.EndDate.Value < this.StartDate) 
         return true; 
        if (this.EndDate.HasValue && other.EndDate.Value < this.EndDate.Value) 
         return true; 
       } 
      } 

      return false; 
     } 
    } 
+0

哇,这是一个野兽:) – 2010-04-20 01:32:48

+2

伟大的问题,但我可以建议一个更好的名字?如何“简洁的方式来判断两个DateTime对是否重叠?” – 2010-04-20 01:38:56

+1

通过尝试/如果 - 套住所有可能的星座,一个典型的“精神强化”问题。人们通常会立即尝试解决问题,而不是真正考虑问题。解决方案然后变得更容易,更可能是一个很好的清晰的解决方案。 – 2010-04-20 01:43:50

回答

15
public bool Overlaps(TimePeriod other) 
{ 
    return (other.StartDate >= StartDate && 
       (EndDate == null || other.StartDate <= EndDate.Value)) || 
      (StartDate >= other.StartDate && 
       (other.EndDate == null || StartDate <= other.EndDate.Value)) 
} 
+0

@Adam,检查你的算法...首先比较必须是startdate和enddate,而不是两个startdates。 startdate = 5 jan,enddate = 10jan; other.start = 1 Jan,other.enddate = 1 2月将返回false – 2010-04-20 01:44:51

+1

@Charles:不,它不会。 StartDate> other.StartDate && StartDate 2010-04-20 02:03:39

+0

@亚当,对不起,我的错误,年算法是正确的... – 2010-04-20 02:21:48

3

检查了这一点:DateTimeOverlaps

非常普遍,在所有变量都为空的日期时间,然后

return (StartA.HasValue? StartA.Value:DateTime.Minimum) <= 
      (EndB.HasValue? EndB.Value:DateTime.Maximum) && 
      (EndA.HasValue? EndA.Value:DateTime.Maximum) >= 
       (StartB.HasValue? StartB.Value:DateTime.Minimum); 

的概念,(如链接解释)是非常简单的,并且是简单简洁上述表示。

如果开始在其他结束之前,并且结束在另一个开始之后,则有重叠。这就是说,所有这一切都是必要的,只需一个简单的句子和两个子句,而且你写的任何代码应该简洁地映射到这个简单的概念而不会混淆它。增加额外的不必要的复杂性不会增加理解,它只会增加长度。

故障情况1:TopStart AFTER其他完 - 失败

 |----------| 
|--| 

故障情况2:TopEnd AFTER其他启动 - 失败

|-----------| 
        |------| 

在所有其他情况下,开始是另一端前,和结束是在其他开始之后。

情况A

|----------| 
|-----| 

情况B

| ---------| 
|-------------------| 

情况C

|-----------| 
    |------| 

情况下d

|-----------| 
     |-------------| 
+0

不要认为它处理null结束日期 – Joshscorp 2010-04-20 01:23:21

+0

@Titan,这很容易通过轻微修改... – 2010-04-20 01:48:22

11

这个怎么样:

public bool Overlaps(TimePeriod other) 
{ 
    bool isOtherEarlier = this.StartDate > other.StartDate; 
    TimePeriod earlier = isOtherEarlier ? other : this; 
    TimePeriod later = isOtherEarlier ? this : other; 
    return !earlier.EndDate.HasValue || earlier.EndDate > later.StartDate; 
} 
+0

不像亚当斯解决方案一行,但我认为更可读。但这可能只是一个品味问题。 – 2010-04-20 01:35:04

+0

这也错了...首先比较必须检查this.StartDate against other.endDate – 2010-04-20 01:54:58

+2

@Charles:你在这里也是不正确的。 – 2010-04-20 02:07:54

2

任何你正在处理的纯布尔逻辑的时候,你可以提炼你的算法到一个单独的语句。但不要以为你可以,你应该这样做。除非性能至关重要,否则请始终使用紧凑代码进行可读代码。 (不,紧凑==性能,必然)

这是很容易读,因为它是完全由单一和表情,并且很明显,他们都确定非重叠:

public bool Overlaps(TimePeriod other) 
{ 
    if (other.EndDate.HasValue && other.EndDate < StartDate) 
     return false; 

    if (EndDate.HasValue && EndDate < other.StartDate) 
     return false; 

    if (!EndDate.HasValue && other.EndDate < StartDate) 
     return false; 

    if (!other.EndDate.HasValue && EndDate < other.StartDate) 
     return false; 

    return true; 
} 

这并不是说其他答案是不好的(我喜欢亚当的格式,显然是为了方便阅读而设计的)。我只是这么说,因为很明显你是初学者,我认为这是一个不足够的教训(我很内疚)。有人(我认为马丁福勒)曾经说过这样的话:“任何傻瓜都可以编写计算机可以理解的代码,但一个好的程序员可以编写人们可以理解的代码。”

相关问题