了解年龄验证逻辑的条件

时间:2017-12-07 05:08:23

标签: java date calendar

我试图根据出生日期计算出这个人的年龄,如果超过18岁的话,我会做一些逻辑。我编写了我的代码并且工作正常,但我偶然发现了一个我在网上发现的代码并且我没有得到一个条件。代码是:

public class AgeValidation {
public static void main(String[] args) {
    getAge("29-12-1999");
}

private static void getAge(String dob1) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
    Date dob;
    try {
        dob = format.parse(dob1);
        Calendar dob2 = Calendar.getInstance();
        dob2.setTime(dob);
        Calendar today = Calendar.getInstance();
        int age = today.get(Calendar.YEAR) - dob2.get(Calendar.YEAR);

        if(dob2.after(today)) {
            System.out.println("Future date not allowed");
            System.exit(0);
        }

        if (today.get(Calendar.MONTH) < dob2.get(Calendar.MONTH)) {
            System.out.println("First if condition");
            age--;
        } else if (today.get(Calendar.MONTH) == dob2.get(Calendar.MONTH)
                && today.get(Calendar.DAY_OF_MONTH) < dob2.get(Calendar.DAY_OF_MONTH)) {
            System.out.println("else if condition");
            age--;
        }

        if (age < 18) {
            System.out.println(age);
            System.out.println("Underage");
        } else {
            System.out.println(age);
            System.out.println("18 years");
            //Some logic
        }
    } catch (ParseException e) {

        e.printStackTrace();
    }
}
}

需要解决以下问题:

  1. 如果DOB年份在本年之后,我已经添加了一个条件,它不应该继续。

    if(dob2.after(today)) {
        System.out.println("Future date not allowed");
        System.exit(0);
    }
    
  2. 使用System.exit(0);是否正确,或者是否有更好的方法可以阻止进一步执行。

    1. 在我在网上找到的代码中,我看到了一个条件

      ` if (today.get(Calendar.MONTH) < dob2.get(Calendar.MONTH))`
      

      我没有得到执行的方案。

    2. 是否存在此代码无效的用例(我无法想到)

2 个答案:

答案 0 :(得分:2)

java.time

您不应该(因为没有)想要使用长期过时的类SimpleDateFormatDateCalendar。特别是第一个是出了名的麻烦,但我们在java.time中更好地替换了所有这些,现代Java日期和时间API也被称为JSR-310。

更是如此,因为现代API有一种计算内置两个日期之间年份的方法。编写代码不仅更容易,更重要的是它更容易阅读和理解,并且您可以更加确定正确性。

private static final DateTimeFormatter dateFormatter 
        = DateTimeFormatter.ofPattern("dd-MM-uuuu");

private static void getAge(String dob1) {
    LocalDate dob = LocalDate.parse(dob1, dateFormatter);
    LocalDate today = LocalDate.now(ZoneId.of("Asia/Dushanbe"));
    if (dob.isAfter(today)) {
        System.out.println("Future date not allowed");
    } else {
        int age = (int) ChronoUnit.YEARS.between(dob, today);

        if (age < 18) {
            System.out.println(age);
            System.out.println("Underage");
        } else {
            System.out.println(age);
            System.out.println("18 years");
            //Some logic
        }
    }
}

以示例日期"29-12-1999"打印上述方法:

17
Underage

由于所有时区的日期都不一样,请替换您所需的时区而不是亚洲/杜尚别。

between()返回long。在这种情况下,我们可以安全地将其转换为int,因为LocalDate仅处理-999 999 999到999 999 999范围内的年份,因此年份的差异永远不会超过{{1}的容量}}

您的问题

  1. 使用int通常是有问题的,但有时是必要的。在我的代码中,我使用System.exit(0); - if构造避免了它。另一种选择是else。我想如果在return;之后有两次调用之后,这会更多地给你你想要的东西。另一种选择是抛出一个getAge(),这将留给呼叫者决定是否抓住它。
  2. 在12月份运行代码时,不会执行您引用的行。想象一下,明年1月运行你的代码,然后今天的月份将是1月,而IllegalArgumentException的月份仍然是12月,所以自1月份到12月之前,代码将被执行。您的方法计算正确的年龄也是必要的。
  3. 代码似乎令人费解,正如Jim Garrison所说,但看起来是正确的(即使过时的API也不需要这么复杂)。我没有发现一个无法正确处理的案件。
  4. 问题:我可以在Java版本中使用现代API吗?

    如果至少使用Java 6 ,则可以。

    • 在Java 8及更高版本中,内置了新的API。
    • 在Java 6和7中获取the ThreeTen Backport,新类的backport({3}}的ThreeTen)。
    • 在Android上,使用Android版的ThreeTen Backport。它被称为ThreeTenABP,在JSR 310中有详尽的解释。

    要学习使用dob2,请参阅this question: How to use ThreeTenABP in Android Project或在网上查找其他资源。

答案 1 :(得分:-1)

我正在给你一个不关心闰年逻辑的解决方案。但你可以建立在这种方法的基础上。

public static void main(String[] args) throws Exception{
    String date ="11_10_1991";

    SimpleDateFormat sdf = new SimpleDateFormat("dd_MM_yyyy");
    Date birthDate = sdf.parse(date);

    long ageInMillis = System.currentTimeMillis() - birthDate.getTime();

    long years = ageInMillis /(365 * 24*60*60*1000l);

    long leftover = ageInMillis %(365 * 24*60*60*1000l);
    long days = leftover/(24*60*60*1000l);

    System.out.println(years);
    System.out.println(days);

}