概要

営業日計算や帳票の日付処理で、日本の祝日を判定する必要は頻繁に生じます。しかし Java 標準 API には祝日カレンダーが含まれていないため、自前でリストを管理するか、外部データを取り込む仕組みが必要です。祝日法は改正されることがあり、春分の日・秋分の日は天文計算に基づくため、ハードコードだけでは運用が回らない場面も出てきます。この記事では、祝日データを定数リストとして管理しつつ、年ごとの更新を容易にする構成を紹介します。振替休日の自動算出ルールや、春分・秋分の近似計算、営業日ロジックへの接続方法も含め、実務でそのまま使える形に整えます。

使いどころ

年度ごとの祝日マスタを CSV から読み込み、営業日判定に使う

帳票の出力日が祝日に当たる場合に前営業日にスライドさせる

カレンダー表示で祝日に色を付ける処理のデータソースにする

コード例

祝日一覧を LocalDate リストで管理する
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.List;

public class JapanHolidays {

    // 固定日の祝日
    public static List<LocalDate> getFixedHolidays(int year) {
        return List.of(
            LocalDate.of(year, Month.JANUARY, 1),   // 元日
            LocalDate.of(year, Month.FEBRUARY, 11),  // 建国記念の日
            LocalDate.of(year, Month.FEBRUARY, 23),  // 天皇誕生日
            LocalDate.of(year, Month.APRIL, 29),     // 昭和の日
            LocalDate.of(year, Month.MAY, 3),        // 憲法記念日
            LocalDate.of(year, Month.MAY, 4),        // みどりの日
            LocalDate.of(year, Month.MAY, 5),        // こどもの日
            LocalDate.of(year, Month.AUGUST, 11),    // 山の日
            LocalDate.of(year, Month.NOVEMBER, 3),   // 文化の日
            LocalDate.of(year, Month.NOVEMBER, 23)   // 勤労感謝の日
        );
    }

    // 第 n 月曜日を返す(Happy Monday 制度)
    public static LocalDate nthMonday(int year, Month month, int n) {
        var first = LocalDate.of(year, month, 1);
        var offset = (DayOfWeek.MONDAY.getValue()
            - first.getDayOfWeek().getValue() + 7) % 7;
        return first.plusDays(offset + 7L * (n - 1));
    }

    // 固定日 + Happy Monday 祝日を結合
    public static List<LocalDate> getHolidays(int year) {
        var holidays = new ArrayList<>(getFixedHolidays(year));
        holidays.add(nthMonday(year, Month.JANUARY, 2));   // 成人の日
        holidays.add(nthMonday(year, Month.JULY, 3));       // 海の日
        holidays.add(nthMonday(year, Month.SEPTEMBER, 3));  // 敬老の日
        holidays.add(nthMonday(year, Month.OCTOBER, 2));    // スポーツの日
        // 春分・秋分の近似計算、振替休日は省略
        // 完全な実装は japan-holidays ツールを参照
        holidays.sort(LocalDate::compareTo);
        return holidays;
    }

    public static void main(String[] args) {
        var holidays = getHolidays(2025);
        holidays.forEach(h ->
            System.out.println(h + " (" + h.getDayOfWeek() + ")")
        );
    }
}

Java 8 / 17 / 21 の完全なサンプルコードは GitHub リポジトリ で確認できます。

Version Coverage

Set.of() でイミュータブルな祝日セットを簡潔に初期化できる。var と toList() で記述量が減る。

Java 17
// Java 17: Set.of() + var + Set.copyOf で簡潔に
var base = Set.of(
    LocalDate.of(2024, 1, 1),
    LocalDate.of(2024, 1, 8)
);
// 振替休日を追加してイミュータブルな Set を返す
var result = new TreeSet<>(base);
// ... 振替休日の追加処理 ...
return Set.copyOf(result);

Library Comparison

標準 API(LocalDate + Set)祝日データを自前で管理し、振替休日・国民の休日のルールもコードで表現したいとき。依存ゼロで動作する。祝日データの年次更新や春分・秋分の計算は自前で行う必要がある。
ICU4J JapaneseCalendar国際化対応で和暦・祝日を扱う場合。JAR サイズが大きく(約11MB)、祝日の独自定義は別途必要。
Jollyday各国の祝日データをライブラリに委ねたいとき。日本の法改正への追従が遅れる場合がある。会社休業日は結局自前で追加が必要。

注意点

春分の日・秋分の日は天文計算に基づくため、数年先の日付は暫定値になる。

祝日法の改正で祝日が追加・変更される可能性がある。

振替休日は「祝日が日曜に当たった場合、翌月曜が休日」というルール。

FAQ

祝日データは毎年手動で更新するのですか?

内閣府の公開CSVを年初に取り込むバッチを組むのが現実的です。閣議決定で祝日が追加・移動されるため、自動取得の仕組みがあると安心です。

振替休日を自動判定できますか?

祝日が日曜なら翌月曜を振替休日とするルールをコードで表現できます。国民の祝日に関する法律第3条に基づく判定ロジックを実装します。

祝日リストをDBで管理すべきですか?

更新頻度が年1回程度なら定数管理で十分です。複数サービスで共有する場合や頻繁な変更がある場合はDB管理を検討します。

関連書籍

この記事のテーマをさらに深く学びたい方へ。

※ Amazon アソシエイトリンクを含みます