Я хочу вернуть возраст в годах в виде int в методе Java. Сейчас у меня есть следующее, где getBirthDate() возвращает объект Date (с датой рождения ;-)):
Но поскольку getYear() устарела, мне интересно, есть ли лучший способ сделать это? Я даже не уверен, что это работает правильно, поскольку у меня нет модульных тестов (пока).
К настоящему времени все должны использовать JDK 8. У всех более ранних версий закончился срок поддержки.
Ответ 2
Ознакомьтесь с Joda, которая упрощает вычисления даты и времени (Joda также является основой нового стандартного Java date / time API, так что вы скоро освоите API, который станет стандартным).
РЕДАКТИРОВАТЬ: Этот ответ предшествует классам даты и времени Java 8 и больше не является текущим.
Ответ 3
Современный ответ и обзор
a) Java-8 (java.time-package)
LocalDatestart= LocalDate.of(1996, 2, 29); LocalDateend= LocalDate.of(2014, 2, 28); // use for age-calculation: LocalDate.now() longyears= ChronoUnit.YEARS.between(start, end); System.out.println(years); // 17
Обратите внимание, что выражение LocalDate.now() неявно связано с системным часовым поясом (который часто упускается из виду пользователями). Для наглядности обычно лучше использовать перегруженный метод, now(ZoneId.of("Europe/Paris")) указывающий явный часовой пояс (здесь "Европа / Париж" в качестве примера). Если запрашивается системный часовой пояс, то я лично предпочитаю писать LocalDate.now(ZoneId.systemDefault()) чтобы сделать связь с системным часовым поясом более четкой. Это требует больше усилий при написании, но облегчает чтение.
б) Joda-Time
Пожалуйста, обратите внимание, что предложенное и принятое решение Joda-Time- дает другой результат вычисления для дат, показанных выше (редкий случай), а именно:
LocalDatebirthdate=newLocalDate(1996, 2, 29); LocalDatenow=newLocalDate(2014, 2, 28); // test, in real world without args Yearsage= Years.yearsBetween(birthdate, now); System.out.println(age.getYears()); // 18
Я рассматриваю это как небольшую ошибку, но команда Joda придерживается другого взгляда на это странное поведение и не хочет его исправлять (странно, потому что день месяца в конечной дате меньше даты начала, поэтому год должен быть на один меньше). Смотрите также этот закрытый выпуск.
c) java.util.Календарь и т.д.
Для сравнения смотрите Другие ответы. Я бы вообще не рекомендовал использовать эти устаревшие классы, потому что результирующий код по-прежнему содержит ошибки в некоторых экзотических случаях и / или слишком сложный, учитывая тот факт, что исходный вопрос звучит так просто. В 2015 году у нас появились действительно лучшие библиотеки.
d) О Date4J:
Предлагаемое решение простое, но иногда дает сбой в случае високосных лет. Простая оценка дня года ненадежна.
e) Моя собственная библиотека Time4J:
Это работает аналогично Java-8-solution. Просто замените LocalDate на PlainDate и ChronoUnit.YEARS на CalendarUnit.YEARS. Однако для получения "сегодня" требуется явная ссылка на часовой пояс.
PlainDatestart= PlainDate.of(1996, 2, 29); PlainDateend= PlainDate.of(2014, 2, 28); // use for age-calculation (today): // => end = SystemClock.inZonalView(EUROPE.PARIS).today(); // or in system timezone: end = SystemClock.inLocalView().today(); longyears= CalendarUnit.YEARS.between(start, end); System.out.println(years); // 17
Ответ 4
Calendarnow= Calendar.getInstance(); Calendardob= Calendar.getInstance(); dob.setTime(...); if (dob.after(now)) { thrownewIllegalArgumentException("Can't be born in the future"); } intyear1= now.get(Calendar.YEAR); intyear2= dob.get(Calendar.YEAR); intage= year1 - year2; intmonth3= now.get(Calendar.MONTH); intmonth2= dob.get(Calendar.MONTH); if (month2 > month3) { age--; } elseif (month3 == month2) { intday1= now.get(Calendar.DAY_OF_MONTH); intday2= dob.get(Calendar.DAY_OF_MONTH); if (day2 > day1) { age--; } } // age is now correct