簡體   English   中英

為什么此Java代碼具有此年齡驗證日期比較?

[英]Why does this Java code have this age validation date comparison?

這是對有關使用Java計算年齡的問題 的答復

/**
 * This Method is unit tested properly for very different cases , 
 * taking care of Leap Year days difference in a year, 
 * and date cases month and Year boundary cases (12/31/1980, 01/01/1980 etc)
**/

public static int getAge(Date dateOfBirth) {

    Calendar today = Calendar.getInstance();
    Calendar birthDate = Calendar.getInstance();

    int age = 0;

    birthDate.setTime(dateOfBirth);
    if (birthDate.after(today)) {
        throw new IllegalArgumentException("Can't be born in the future");
    }

    age = today.get(Calendar.YEAR) - birthDate.get(Calendar.YEAR);

    // If birth date is greater than todays date (after 2 days adjustment of leap year) then decrement age one year   
    if ( (birthDate.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR) > 3) ||
            (birthDate.get(Calendar.MONTH) > today.get(Calendar.MONTH ))){
        age--;

     // If birth date and todays date are of same month and birth day of month is greater than todays day of month then decrement age
    }else if ((birthDate.get(Calendar.MONTH) == today.get(Calendar.MONTH )) &&
              (birthDate.get(Calendar.DAY_OF_MONTH) > today.get(Calendar.DAY_OF_MONTH ))){
        age--;
    }

    return age;
}

這段代碼可以正常工作,但是為什么要進行以下比較: (birthDate.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR) > 3)

我已經盡力創建了一個巨大的電子表格,其中包含一年中的全天差異,以嘗試查看它可能涵蓋的情況,但是我看不到其他比較未涵蓋的任何內容。 誰能解釋包括此比較的目的? 以某種方式更有效嗎?

以下來自ThreetenBP (Java-8的反向端口)的代碼示例支持以下聲明: 不需要進行年度檢查

@Override 
public long until(Temporal endExclusive, TemporalUnit unit) { 
LocalDate end = LocalDate.from(endExclusive); 
    if (unit instanceof ChronoUnit) { 
         switch ((ChronoUnit) unit) { 
             case DAYS: return daysUntil(end); 
             case WEEKS: return daysUntil(end) / 7; 
             case MONTHS: return monthsUntil(end); 
             case YEARS: return monthsUntil(end) / 12; 
             case DECADES: return monthsUntil(end) / 120; 
             case CENTURIES: return monthsUntil(end) / 1200; 
             case MILLENNIA: return monthsUntil(end) / 12000; 
             case ERAS: return end.getLong(ERA) - getLong(ERA); 
         } 
         throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); 
     } 
     return unit.between(this, end); 
} 

[...]     

private long monthsUntil(LocalDate end) { 
   long packed1 = getProlepticMonth() * 32L + getDayOfMonth();  // no overflow 
   long packed2 = end.getProlepticMonth() * 32L + end.getDayOfMonth();  // no overflow 
   return (packed2 - packed1) / 32; 
} 

case YEARS: return monthsUntil(end) / 12; (表達式YEARS.between(birthday, today) birthday.until(today, YEARS)YEARS.between(birthday, today)是等效的-一個委托給其他人)采用了與OP引用的以下簡化代碼相同的算法,並且未引用任何一天的今年檢查:

age = today.get(Calendar.YEAR) - birthDate.get(Calendar.YEAR);

if (birthDate.get(Calendar.MONTH) > today.get(Calendar.MONTH)) {
    age--;
}else if ((birthDate.get(Calendar.MONTH) == today.get(Calendar.MONTH )) &&
          (birthDate.get(Calendar.DAY_OF_MONTH) > today.get(Calendar.DAY_OF_MONTH ))){
    age--;
}

問題出現了: 為什么要進行年度檢查?

a)海報原本是認真對待年度想法的,后來又忘了清理

b)張貼者希望“改善”表演

以下Java-8代碼演示了如果認真對待並作為完整版本,則說明基於年日的算法的問題(庫的選擇在這里無關緊要,僅算法很重要):

LocalDate birthday = LocalDate.of(2001, 3, 6);
LocalDate today = LocalDate.of(2016, 3, 5); // leap year

int age = today.getYear() - birthday.getYear();
if (birthday.getDayOfYear() > today.getDayOfYear()) {
    age--;
}
System.out.println("age based on day-of-year: " + age); // 15 (wrong)
System.out.println("age based on month and day-of-month: " 
  + ChronoUnit.YEARS.between(birthday, today)); // 14 (correct)

結論:

您引用的建議的年度條款僅是噪音,因為算法的其余部分與Java-8的功能相對應。 年度檢查可能源自某些較早的基於年度建議代碼的版本,並且尚未被清除。

為了回答您的最后一個問題:像這樣不必要的檢查不是好辦法。 就性能而言是高效的(盡管我們在這里談論微優化)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM