2017-01-12 4 views
2

Meine Methode funktioniert, da ich nur den Unterschied in Jahren wissen möchte, mein Problem ist, dass ich so ineffizient dabei bin. Ich habe das Gefühl, dass es viel einfacher und ästhetisch angenehmer ist, die Methode zu schreiben.Eine Methode, um den Unterschied zwischen zwei Daten zu finden

Edit: Ich muss meine eigene Methode schreiben. Ich ziehe es auch vor, nicht aus dem Weg zu gehen und fortgeschrittene Dinge zu verwenden, etwas im Bereich eines Programmierers für das erste Jahr.

public int differenceInYears(MyDate comparedDate) { 
     int difference = 0; 
     if (this.year > comparedDate.year) { 
      if (this.month > comparedDate.month) { 
       difference = this.year - comparedDate.year; 
      } 
      else if (this.month == comparedDate.month) { 
       if (this.day >= comparedDate.day) { 
        difference = this.year - comparedDate.year; 
       } 
       else { 
        difference = this.year - comparedDate.year - 1; 
       } 
      } 
      else { 
       difference = this.year - comparedDate.year - 1; 
      } 
     } 
     if (comparedDate.year > this.year) { 
      if (comparedDate.month > this.month) { 
       difference = comparedDate.year - this.year; 
      } 
      else if (comparedDate.month == this.month) { 
       if (comparedDate.day >= this.day) { 
        difference = comparedDate.year - this.year; 
       } 
       else { 
        difference = comparedDate.year - this.year - 1; 
       } 
      } 
      else { 
       difference = comparedDate.year - this.year - 1; 
      } 
     } 
     return difference; 
    } 

werde ich die MyDate Klasse unten Kontext hinzufügen:

public class MyDate { 

    private int day; 
    private int month; 
    private int year; 

    public MyDate(int day, int montd, int year) { 
     this.day = day; 
     this.month = montd; 
     this.year = year; 
    } 

    public String toString() { 
     return this.day + "." + this.month + "." + this.year; 
    } 

    public boolean earlier(MyDate compared) { 
     if (this.year < compared.year) { 
      return true; 
     } 

     if (this.year == compared.year && this.month < compared.month) { 
      return true; 
     } 

     if (this.year == compared.year && this.month == compared.month 
       && this.day < compared.day) { 
      return true; 
     } 

     return false; 
    } 
+0

Mögliches Duplikat von [Berechnung der Differenz zwischen zwei Java-Datumsinstanzen] (http://stackoverflow.com/questions/1555262/calculating-the-difference-between-two-java-date-instances) –

+0

Müssen Sie tun schreibe diese Methode selbst? Es wäre viel besser, einen integrierten Bibliotheksaufruf zu verwenden. –

+0

Es ist ein 'MyDate' Objekt. Er hat es selbst geschrieben. Ich denke, –

Antwort

3

ich, dass Ihre Methode richtig funktioniert wird vermuten. Wie kann es verbessert werden? Das erste, was Sie tun können, ist die Beseitigung aller wiederholten this.year - comparedDate.year und comparedDate.year - this.year Berechnungen. Sie tun sie, egal was, also lassen Sie uns sie an die Spitze ihrer jeweiligen if Blöcke setzen.

public int differenceInYears(MyDate comparedDate) { 
    int difference; 

    if (this.year > comparedDate.year) { 
     difference = this.year - comparedDate.year; 

     if (this.month > comparedDate.month) { 
     } 
     else if (this.month == comparedDate.month) { 
      if (this.day >= comparedDate.day) { 
      } 
      else { 
       difference -= 1; 
      } 
     } 
     else { 
      difference -= 1; 
     } 
    } 
    if (comparedDate.year > this.year) { 
     difference = comparedDate.year - this.year; 

     if (comparedDate.month > this.month) { 
     } 
     else if (comparedDate.month == this.month) { 
      if (comparedDate.day >= this.day) { 
      } 
      else { 
       difference -= 1; 
      } 
     } 
     else { 
      difference -= 1; 
     } 
    } 

    return difference; 
} 

Als nächstes werden wir diese leeren Zweige loswerden.

public int differenceInYears(MyDate comparedDate) { 
    int difference; 

    if (this.year > comparedDate.year) { 
     difference = this.year - comparedDate.year; 

     if (this.month == comparedDate.month) { 
      if (this.day < comparedDate.day) { 
       difference -= 1; 
      } 
     } 
     else if (this.month < comparedDate.month) { 
      difference -= 1; 
     } 
    } 
    if (comparedDate.year > this.year) { 
     difference = comparedDate.year - this.year; 

     if (comparedDate.month == this.month) { 
      if (comparedDate.day < this.day) { 
       difference -= 1; 
      } 
     } 
     else if (comparedDate.month < this.month) { 
      difference -= 1; 
     } 
    } 

    return difference; 
} 

Nun wollen wir sehen, ob wir nicht zusammen, einige der Bedingungen mit && und || quetschen.

public int differenceInYears(MyDate comparedDate) { 
    int difference; 

    if (this.year > comparedDate.year) { 
     difference = this.year - comparedDate.year; 

     if (this.month == comparedDate.month && this.day < comparedDate.day || 
      this.month < comparedDate.month) 
     { 
      difference -= 1; 
     } 
    } 
    if (comparedDate.year > this.year) { 
     difference = comparedDate.year - this.year; 

     if (comparedDate.month == this.month && comparedDate.day < this.day || 
      comparedDate.month < this.month) 
     { 
      difference -= 1; 
     } 
    } 

    return difference; 
} 

Diese beiden Blöcke sehen furchtbar ähnlich aus, nicht wahr? Wir könnten sie kombinieren, indem wir this und comparedDate bedingt austauschen. Lassen Sie a und b das frühere und spätere Datum sein.

public int differenceInYears(MyDate comparedDate) { 
    MyDate a = (this.year < comparedDate.year) ? this : comparedDate; 
    MyDate b = (this.year < comparedDate.year) ? comparedDate : this; 

    int difference = b.year - a.year; 

    if (a.year < b.year) { 
     if (a.month == b.month && a.day < b.day || 
      a.month < b.month) 
     { 
      difference -= 1; 
     } 
    } 

    return difference; 
} 

Und ein letzter Squeeze.

public int differenceInYears(MyDate comparedDate) { 
    MyDate a = (this.year < comparedDate.year) ? this : comparedDate; 
    MyDate b = (this.year < comparedDate.year) ? comparedDate : this; 

    int difference = b.year - a.year; 

    if (a.year < b.year && 
     (a.month == b.month && a.day < b.day || 
     a.month < b.month)) 
    { 
     difference -= 1; 
    } 

    return difference; 
} 
+0

Sehr gut erklärt! –

+0

Das ist schön, danke! – Budaika

0

Der entscheidende Punkt hier ist: manchmal „komplex“ Berechnungen erforderlich sind.

In diesem Sinne: Mach dir keine Sorgen über Ineffizienz. Sie sollten Ihre Zeit damit verbringen, wirklich lesbaren Code zu schreiben. sehr ähnlich wie die Antwort von John dich führt. Im Allgemeinen würden Sie auf Prinzipien wie das "single layer of abstraction" Prinzip zum Beispiel schauen; um solche langwierigen Kaskaden zu vermeiden.

Der andere wichtige Punkt: solche Zuweisungen sind perfekt für Komponententests. Mit anderen Worten: Sie sollten mit dem Schreiben kleiner Testfälle beginnen, die Ihre Methode einfach mit verschiedenen (vorausgewählten) Eingabedaten aufrufen; um dann zu überprüfen, ob das erwartete Ergebnis zurückgegeben wird.

Mit anderen Worten:

Sie zuerst Fokus auf eine Menge von Testfällen zu schreiben, die Sie können Sie feststellen, dass Ihre Implementierung korrekt ist ... denn das ermöglicht es Ihnen refactor Code ohne Angst zu haben von brechen es.

JUnit verwenden ist so einfach wie:

@Test 
public testDifferenceIs0 { 
    MyDate thisYear = new MyDate(1,1,2017); 
    MyDate thisYearToo = new MyDate(1,1,2017); 
    assertThat(thisYear.differenceInYears(thisYearToo), is(0)); 
} 

zum Beispiel.

1

Okay, so nach einiger Überlegung, ich denke, das ein bisschen schöner aussehen:

public int differenceInYears(MyDate comparedDate){ 
    //Calculate days total 
    long daysTotalThisDate = this.year * 365 + this.month * 30 + this.day; 
    long daysTotalComparedDate = comparedDate.year * 365 + comparedDate.month * 30 + comparedDate.day; 

    //Get absolute value 
    long differenceInDays = daysTotalThisDate - daysTotalComparedDate; 
    if (differenceInDays < 0){ 
     differenceInDays *= -1; 
    } 

    //the (int) cast will always round down, so anything under 365 will be 0 
    return (int) differenceInDays/365; 
} 

Diese Rechnung Sprung dauert nicht Jahre.

Bevor Leute denken, meine Berechnung von daysTotal... ist falsch. Du hast Recht. Aber ich habe es falsch gemacht für beide Berechnungen, also ist das Endergebnis immer noch in Ordnung, wenn man bedenkt, dass wir nur den Unterschied im Jahr und nicht in den Tagen berechnen müssen.

+0

Ich weiß, dass die Berechnung nicht korrekt ist, aber das Endergebnis ist immer noch. da wir einen int zurückgeben: ob wir 30/365 oder 29/365 zurückgeben. In beiden Fällen wird 0 zurückgegeben. –

+1

Es ist durch Zufall, dass dies funktionieren kann. Diese Antwort ist unvollständig, ohne die Nuancen zu erklären. Genauer gesagt funktioniert es, weil die durchschnittliche Anzahl von Tagen für einen Monat (30.417) größer ist als der längste Monat (31), subtrahiere 1 (30). Wenn diese Tatsache nicht wahr wäre, könntest du das nicht tun. – Cruncher

+0

Ich sehe es jetzt. Du bist in der Tat richtig. Vor allem, wenn die Jahre auseinander liegen. Danke, dass du das geklärt hast! –

Verwandte Themen