年齢計算のゴールイメージ
「生年月日から現在の年齢を出したい」「基準日時点での年齢を知りたい」
業務システムだと、会員管理・保険・年齢制限チェックなどで“年齢”はよく出てきます。
ここで一番やってはいけないのは、「現在の年 − 生まれた年」で計算してしまうことです。
誕生日を迎えているかどうかで年齢は変わるので、それだけでは必ずズレます。
Java では、LocalDate と Period(または ChronoUnit.YEARS)を使うことで、
「誕生日を過ぎているかどうかも含めて、正しい年齢」を簡潔に計算できます。
LocalDate と Period を使った基本的な年齢計算
Period.between(生年月日, 基準日) の years を使う
一番素直で“意味が伝わる”書き方です。
import java.time.LocalDate;
import java.time.Period;
public class AgeByPeriod {
public static void main(String[] args) {
LocalDate birthday = LocalDate.of(1990, 3, 26); // 生年月日
LocalDate today = LocalDate.of(2025, 3, 26); // 基準日(例として固定)
Period period = Period.between(birthday, today);
int age = period.getYears();
System.out.println("生年月日 : " + birthday); // 1990-03-26
System.out.println("基準日 : " + today); // 2025-03-26
System.out.println("年齢 : " + age); // 35
}
}
Javaここで重要なのは、Period.between が
「年・月・日」の差を“カレンダーとして”計算してくれることです。
period.getYears() は、
「誕生日を迎えているかどうかを含めた“満年齢”」を返してくれます。
つまり、
単に today.getYear() - birthday.getYear() をしているわけではなく、
「今年の誕生日を過ぎているかどうか」も考慮した結果になっています。
誕生日を迎えていないケースの確認
今年の誕生日前と後でどう変わるか
誕生日を迎える前と後で、年齢が 1 歳変わることを確認してみましょう。
import java.time.LocalDate;
import java.time.Period;
public class AgeBeforeAfterBirthday {
public static void main(String[] args) {
LocalDate birthday = LocalDate.of(1990, 10, 10);
LocalDate before = LocalDate.of(2025, 10, 9); // 誕生日の前日
LocalDate after = LocalDate.of(2025, 10, 10); // 誕生日当日
int ageBefore = Period.between(birthday, before).getYears();
int ageAfter = Period.between(birthday, after).getYears();
System.out.println("誕生日前日 時点の年齢 : " + ageBefore); // 34
System.out.println("誕生日当日 時点の年齢 : " + ageAfter); // 35
}
}
Javaここで深掘りしたいのは、
「年齢とは“年の差”ではなく、“誕生日を何回迎えたか”」ということです。
Period.between は、
「生年月日から基準日までを、年・月・日に分解した結果」を返します。
その years 部分だけを取り出すことで、
“満年齢”を自然に表現できている、という感覚を持ってほしいところです。
ChronoUnit.YEARS を使った年齢計算
ChronoUnit.YEARS.between(生年月日, 基準日)
もう一つよく使われるのが、ChronoUnit.YEARS を使う方法です。
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class AgeByChronoUnit {
public static void main(String[] args) {
LocalDate birthday = LocalDate.of(1990, 3, 26);
LocalDate today = LocalDate.of(2025, 3, 26);
long age = ChronoUnit.YEARS.between(birthday, today);
System.out.println("年齢 : " + age); // 35
}
}
JavaChronoUnit.YEARS.between も、
「誕生日を迎えているかどうか」を考慮した“満年齢”を返してくれます。
Period との違いは、Period は「年・月・日」をまとめて扱えるのに対し、ChronoUnit.YEARS は「年だけ」にフォーカスしている、という点です。
どちらを使っても構いませんが、
「年齢」という文脈では ChronoUnit.YEARS.between の方が
コードを読んだときに意図が伝わりやすい、ということも多いです。
「現在日時点の年齢」を計算する
LocalDate.now() を基準日に使う
実務では、「今日時点の年齢」を知りたいことが多いです。
その場合は、基準日を LocalDate.now() にすれば OK です。
import java.time.LocalDate;
import java.time.Period;
public class AgeToday {
public static void main(String[] args) {
LocalDate birthday = LocalDate.of(1990, 3, 26);
LocalDate today = LocalDate.now();
int age = Period.between(birthday, today).getYears();
System.out.println("今日 : " + today);
System.out.println("年齢 : " + age);
}
}
Javaここでのポイントは、
「基準日を変えれば、任意の時点での年齢が計算できる」
という感覚を持つことです。
例えば「契約開始日時点の年齢」「イベント開催日時点の年齢」など、
“今日”ではない日付を基準にしたい場面も多いので、LocalDate.now() に限らず、
「基準日を引数として受け取るメソッド」にしておくと再利用性が高まります。
年齢計算ユーティリティとしてまとめる
calculateAge(birthday, onDate) というメソッドに閉じ込める
年齢計算は、あちこちで同じようなコードを書きがちです。
それを避けるために、ユーティリティメソッドとして一か所にまとめておきましょう。
import java.time.LocalDate;
import java.time.Period;
public class AgeUtils {
public static int calculateAge(LocalDate birthday, LocalDate onDate) {
if (birthday == null || onDate == null) {
throw new IllegalArgumentException("birthday / onDate は null にできません");
}
if (onDate.isBefore(birthday)) {
throw new IllegalArgumentException("基準日が生年月日より前です");
}
return Period.between(birthday, onDate).getYears();
}
public static int calculateAgeToday(LocalDate birthday) {
return calculateAge(birthday, LocalDate.now());
}
public static void main(String[] args) {
LocalDate birthday = LocalDate.of(1990, 3, 26);
int ageToday = calculateAgeToday(birthday);
int ageAt2020 = calculateAge(birthday, LocalDate.of(2020, 4, 1));
System.out.println("今日時点の年齢 : " + ageToday);
System.out.println("2020-04-01 時点の年齢 : " + ageAt2020);
}
}
Javaここで深掘りしたいのは、
「年齢計算の“前提条件”も一緒に閉じ込めている」ことです。
基準日が生年月日より前の場合は例外にする、null は受け付けない、などのルールを
ユーティリティの中に書いておくことで、
呼び出し側のコードがすっきりし、バグも減ります。
実務でよくある年齢関連の注意点
「何歳以上」「何歳未満」の判定
例えば「20 歳以上かどうか」を判定したい場合、
単に age >= 20 とするだけでよいか、を一度立ち止まって考える価値があります。
「基準日時点の年齢」を calculateAge で求めてから >= 20 とするのは、
多くのケースで正しいです。
ただし、
「誕生日当日の 0:00 から 20 歳とみなすのか」
「誕生日の前日までは 19 歳とみなすのか」
など、細かいルールが関係する業務(飲酒・喫煙・選挙など)では、
法的な定義に合わせた実装が必要になることもあります。
ここで大事なのは、
「年齢の定義は業務ルールとセットで考える」
という姿勢です。
時刻を含む場合はどうするか
生年月日や基準日時が LocalDateTime や ZonedDateTime で与えられることもあります。
その場合でも、年齢は基本的に「日付ベース」で考えることが多いので、toLocalDate() で日付に落としてから計算するのが自然です。
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
public class AgeWithDateTime {
public static void main(String[] args) {
LocalDateTime birthdayDateTime = LocalDateTime.of(1990, 3, 26, 15, 30);
LocalDateTime nowDateTime = LocalDateTime.now();
LocalDate birthdayDate = birthdayDateTime.toLocalDate();
LocalDate nowDate = nowDateTime.toLocalDate();
int age = Period.between(birthdayDate, nowDate).getYears();
System.out.println("年齢 : " + age);
}
}
Java「時刻まで含めて厳密に何年何ヶ月何日何時間」といった計算が必要な場合は、Duration や ChronoUnit を組み合わせることになりますが、
“年齢”という文脈では、まずは日付ベースで考えるのが基本です。
まとめ:年齢計算で絶対に覚えてほしいこと
年齢計算は、「生年月日と基準日から“満年齢”を求める」作業です。
単純な「年の差」ではなく、Period.between(birthday, onDate).getYears() やChronoUnit.YEARS.between(birthday, onDate) を使う。
基準日を引数に取るユーティリティメソッドにして、
「今日時点」「ある日付時点」の年齢を柔軟に計算できるようにする。
生年月日より前の基準日や null など、前提条件も一緒にチェックする。
もしあなたのコードのどこかに、today.getYear() - birthday.getYear() のような年齢計算が書かれていたら、
そこを一度 Period や ChronoUnit.YEARS を使った実装に置き換えられないか眺めてみてください。
その小さな置き換えが、
“時間とカレンダーに強いエンジニア”への、確かな一歩になります。
