2017-01-12 128 views
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

[计算两个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; 
} 

这两个块看起来非常相似,不是吗?我们可以通过有条件地交换thiscomparedDate来合并它们。假设ab分别为更早和更晚的日期。

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

最后一个挤压。

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”原则;以避免有这样冗长的if/else级联。

另一个关键点:这样的任务是完美单元测试。换句话说:您应该从编写一些简单的测试用例开始,这些测试用例只需使用各种(预先选择的)输入日期来调用您的方法;然后检查是否返回了预期结果。

换句话说:

你先专注于编写大量的测试用例,你能不能请你确定的你的代码是正确的......因为它使您能够重构你的代码,而不必担心打破吧。

使用JUnit是一样简单:

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

例如。

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...是错误的。你是对的。但是我对两次计算都做错了,所以最终结果还是可以的,因为我们只需要计算一年中的差异,而不是几天。

+0

我知道计算不正确,但最终结果仍然是。因为我们返回一个int:是否我们返回30/365或29/365。在这两种情况下返回0。 –

+1

巧合的是,这可以工作。没有解释细微差别,这个答案是不完整的。具体来说,它的工作原理是一个月的平均天数(30.417)大于最长的月份(31)减去1(30)。如果这个事实不是真的,你将无法做到这一点。 – Cruncher

+0

我现在看到它。你确实是对的。特别是当这些年份更加分离时。谢谢你清理那个! –