2017-01-12 11 views
2

私の方法は、年の違いだけを知りたいので、私の問題は私がこれを行うことで非常に効率が悪いことです。私は、このメソッドを書くのにははるかに単純で審美的に喜ばしい方法があると感じています。2つの日付の違いを見つける方法

編集:私自身の方法を書く必要があります。私はまた、自分のやり方から脱して、初級プログラマーの範囲内にある先進的なものを使うことを好まない。

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

私は、コンテキストの下にMyDateクラスを追加します。

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

[2つのJava日付インスタンス間の差異を計算する]の可能な複製(http://stackoverflow.com/questions/1555262/calculating-the-difference-between-two-java-date-instances) –

+0

あなた自身でこの方法を書いてください。組み込みのライブラリ呼び出しを使用する方がはるかに良いでしょう。 –

+0

これは 'MyDate'オブジェクトです。彼は自分自身で書きました。 –

答えて

3

私はあなたのメソッドが正しく動作することを前提とします。どのように改善することができますか?最初に行うことは、繰り返しのthis.year - comparedDate.yearcomparedDate.year - this.yearの計算をすべて削除することです。あなたは何をしていてもそれらをするので、それぞれのifブロックの上にそれらを置いてみましょう。

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

次に、空のブランチを取り除いてみましょう。

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

今、私たちは&&||と一緒条件の一部を絞ることができない場合を見てみましょう。

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

これらの2つのブロックは非常に似ていますか?条件付きで交換すると、thiscomparedDateを組み合わせることができます。 aおよびbをそれぞれ早期および後日とします。

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

最後に1回絞る。

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

非常によく説明されています! –

+0

これは美しいです、ありがとう! – Budaika

0

ここで重要な点は、「複雑な」計算が必要な場合があることです。

その意味では、非効率的であることを心配しないでください。あなたは本当に読みやすいコードを書くことに時間を費やすべきです。ジョンからの答えがあなたを導いてくれるのと非常によく似ています。一般的には、例えば "single layer of abstraction"の原則のように考えています。そのような長い/そうでないカスケードを避けるために。

その他の重要なポイント:このような割り当ては、となり、ユニットテスト用にはとなります。つまり、さまざまな(あらかじめ選択された)入力日付でメソッドを呼び出すだけの小さなテストケースを作成することから始める必要があります。期待される結果が返されることを確認します。言い換えれば

あなた、あなたの実装が正しいにすることができますあなたがを決定するテストケースの多くを書く上の第1焦点...それは恐れずあなたのコードリファクタリングすることができますので、 が壊れています。です。例えば

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

:JUnitのを使用して

は同様に簡単です。いくつかの考慮後にそう

1

さて、私はこれは少し見た目が良くかもしれないと思う:

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

これは、うるう年を考慮していません。

私の計算がdaysTotal...と間違っていると思う前に、あなたは正しいです。しかし、私は両方の計算でそれが間違っていたので、最終結果は、我々は日数ではなく日数で計算する必要があると考えれば、まだOKです。

+0

私は計算が正しくないことを知っていますが、最終結果はまだです。我々はintを返すので、我々は30/365か29/365を返すかどうか。どちらの場合も0が返されます。 –

+1

これがうまくいくのは偶然のことです。この答えはニュアンスを説明することなく不完全です。具体的には、1か月間の平均日数(30.417)が最も長い月(31)から1(30)を引いた値よりも大きいために機能します。この事実が真実でない場合、あなたはこれを行うことができません。 – Cruncher

+0

私は今それを見る。あなたは本当に正しいです。特に年が離れている場合。それをクリアしていただきありがとうございます! –

関連する問題