2010-04-20 4 views
9

Grundsätzlich möchte ich nur überprüfen, ob eine Zeitperiode mit einer anderen überlappt. Null Enddatum bedeutet bis unendlich. Kann mir jemand das für mich verkürzen, da es manchmal ziemlich schwer zu lesen ist. ProstKann mir jemand diesen Algorithmus für mich vereinfachen?

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

Wow, das ist ein Biest :) –

+2

Große Frage, aber darf ich einen besseren Namen vorschlagen? Wie wäre es mit "Präzise Art zu sagen, ob zwei DateTime-Paare überlappen?" –

+1

Ein typischer Fall von "geistiger Brutalität" ist ein Problem, indem alle möglichen Konstellationen versucht werden. Die Leute versuchen oft sofort, Probleme zu lösen, anstatt wirklich über das Problem nachzudenken. Die Lösung kommt dann viel einfacher und wahrscheinlicher ist es eine gut durchdachte Lösung. –

Antwort

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, Überprüfen Sie Ihren Algorithmus ... Der erste Vergleich muss Startdatum und Enddatum sein, nicht beide Startdaten. startdatum = 5 jan, enddatum = 10jan; other.start = 1 Jan, other.enddate = 1 Feb wird false zurückgeben –

+1

@Charles: Nein, wird es nicht. StartDate> other.StartDate && StartDate

+0

@Adam, tut mir leid, mein Fehler, Ihr Algorithmus ist korrekt ... –

3

Check this out: DateTimeOverlaps

Ganz allgemein, wenn alle Variablen auf NULL festlegbare Datetimes sind, dann

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); 

Das Konzept, (wie im Link beschrieben) ist sehr einfach, und ist einfach und prägnant ausgedrückt oben.

Wenn der Start vor den anderen endet und das Ende nach dem anderen Start ist, haben Sie eine Überlappung. Das sagt alles, und alles, was notwendig ist, in einem einfachen Satz mit zwei Klauseln, und welcher Code auch immer du schreibst, sollte prägnant diesem einfachen Konzept entsprechen, ohne es zu verschleiern. Das Hinzufügen zusätzlicher unnötiger Komplexität fügt kein Verständnis hinzu, sondern fügt nur Länge hinzu.

Ausfallen Fall 1: TopStart NACH anderem Ende - Fehler

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

Ausfallen Fall 2: Topend NACH anderem Start - FAIL

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

In allen anderen Fällen beginnen, bevor anderes Ende ist, und Ende ist nach anderem Start.

Fall A

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

Fall B

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

Fall C

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

Fall D

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

Glauben Sie nicht, dass es behandelt Null Enddatum – Joshscorp

+0

@Titan, dies ist leicht mit kleinen bearbeiten behoben ... –

11

Wie wäre es dieses:

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

Nicht ganz eine Zeile wie Adams Lösung, aber ich denke ein wenig lesbarer. Aber das ist vielleicht nur eine Frage des Geschmacks. –

+0

Das ist auch falsch ... Erster Vergleich muss dies überprüfen.StartDate gegen other.endDate –

+2

@Charles: Sie sind hier auch falsch. –

2

Jedes Mal, wenn mit reinem Boolesche Logik zu tun haben, können Sie Ihren Algorithmus auf eine einzige Aussage destillieren kann. Aber gehen Sie nicht davon aus, dass Sie es tun sollten, nur weil Sie es können. Wenn die Leistung nicht entscheidend ist, sollten Sie stets einen lesbaren Code über den kompakten Code verwenden. (Nicht, dass Kompaktheit == Leistung notwendigerweise)

Dies ist leicht zu lesen, weil es ganz aus Einzel- und Ausdrücke enthalten ist, und es ist offensichtlich, dass sie alle eine Nicht-Überlappung bestimmen:

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

Nicht, dass die andere Antworten sind schlecht (ich mag Adams; seine Formatierung ist offensichtlich auf Lesbarkeit ausgelegt). Ich sage das nur, weil klar ist, dass du ein Anfänger bist, und ich denke, das ist eine Lektion, die nicht genug beachtet wird (ich bin schuldig).Jemand (ich glaube Martin Fowler) sagte einmal so etwas wie: "Jeder Dummkopf kann Code schreiben, den ein Computer versteht, aber ein guter Programmierer kann Code schreiben, den ein Mensch versteht."

Verwandte Themen