Java Tips | 日付・時間:年齢計算

Java Java
スポンサーリンク

年齢計算のゴールイメージ

「生年月日から現在の年齢を出したい」「基準日時点での年齢を知りたい」
業務システムだと、会員管理・保険・年齢制限チェックなどで“年齢”はよく出てきます。

ここで一番やってはいけないのは、「現在の年 − 生まれた年」で計算してしまうことです。
誕生日を迎えているかどうかで年齢は変わるので、それだけでは必ずズレます。

Java では、LocalDatePeriod(または 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
    }
}
Java

ChronoUnit.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 歳とみなすのか」
など、細かいルールが関係する業務(飲酒・喫煙・選挙など)では、
法的な定義に合わせた実装が必要になることもあります。

ここで大事なのは、
「年齢の定義は業務ルールとセットで考える」
という姿勢です。

時刻を含む場合はどうするか

生年月日や基準日時が LocalDateTimeZonedDateTime で与えられることもあります。
その場合でも、年齢は基本的に「日付ベース」で考えることが多いので、
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

「時刻まで含めて厳密に何年何ヶ月何日何時間」といった計算が必要な場合は、
DurationChronoUnit を組み合わせることになりますが、
“年齢”という文脈では、まずは日付ベースで考えるのが基本です。


まとめ:年齢計算で絶対に覚えてほしいこと

年齢計算は、「生年月日と基準日から“満年齢”を求める」作業です。

単純な「年の差」ではなく、
Period.between(birthday, onDate).getYears()
ChronoUnit.YEARS.between(birthday, onDate) を使う。
基準日を引数に取るユーティリティメソッドにして、
「今日時点」「ある日付時点」の年齢を柔軟に計算できるようにする。
生年月日より前の基準日や null など、前提条件も一緒にチェックする。

もしあなたのコードのどこかに、
today.getYear() - birthday.getYear() のような年齢計算が書かれていたら、
そこを一度 PeriodChronoUnit.YEARS を使った実装に置き換えられないか眺めてみてください。

その小さな置き換えが、
“時間とカレンダーに強いエンジニア”への、確かな一歩になります。

タイトルとURLをコピーしました