Сучасна відповідь та огляд
a) Java-8 (java.time-пакет)
LocalDate start = LocalDate.of(1996, 2, 29);
LocalDate end = LocalDate.of(2014, 2, 28); // use for age-calculation: LocalDate.now()
long years = ChronoUnit.YEARS.between(start, end);
System.out.println(years); // 17
Зауважте, що вираз LocalDate.now()
неявно пов'язаний із часовим поясом системи (який користувачі часто не помічають). Для ясності, як правило, краще використовувати перевантажений метод із now(ZoneId.of("Europe/Paris"))
зазначенням явного часового поясу (тут, наприклад, "Європа / Париж"). Якщо запитується часовий пояс системи, то моя особиста перевага - написати, LocalDate.now(ZoneId.systemDefault())
щоб зробити відношення до часового поясу системи чіткішим. Це більше зусиль для письма, але полегшує читання.
б) Джода-час
Зауважте, що запропоноване та прийняте рішення Joda-Time дає різний результат обчислення для вказаних вище дат (рідкісний випадок), а саме:
LocalDate birthdate = new LocalDate(1996, 2, 29);
LocalDate now = new LocalDate(2014, 2, 28); // test, in real world without args
Years age = Years.yearsBetween(birthdate, now);
System.out.println(age.getYears()); // 18
Я вважаю це невеликою помилкою, але команда Joda має інший погляд на цю дивну поведінку і не хоче її виправляти (дивно, оскільки дата закінчення місяця менша, ніж дата початку, тому рік повинен бути один менше). Дивіться також це закрите питання .
в) java.util.Calendar тощо.
Для порівняння див. Різні відповіді. Я б не рекомендував використовувати ці застарілі класи взагалі, оскільки отриманий код все ще є помилковим у деяких екзотичних випадках та / або занадто складним, враховуючи той факт, що оригінальне запитання звучить так просто. У 2015 році ми маємо справді кращі бібліотеки.
г) Про Date4J:
Запропоноване рішення є простим, але іноді буде невдалим у разі високосних років. Просто оцінка дня року не є достовірною.
д) Моя власна бібліотека Time4J :
Це працює аналогічно Java-8-рішенню. Просто замініть LocalDate
на PlainDate
і ChronoUnit.YEARS
на CalendarUnit.YEARS
. Однак для отримання "сьогодні" потрібна чітка посилання на часовий пояс.
PlainDate start = PlainDate.of(1996, 2, 29);
PlainDate end = PlainDate.of(2014, 2, 28);
// use for age-calculation (today):
// => end = SystemClock.inZonalView(EUROPE.PARIS).today();
// or in system timezone: end = SystemClock.inLocalView().today();
long years = CalendarUnit.YEARS.between(start, end);
System.out.println(years); // 17