概要
「この日は休みかどうか」という判定は、営業日計算や納期管理、バッチスケジュールの制御など、業務システムのあちこちで必要になります。曜日だけなら DayOfWeek で済みますが、祝日が絡むと途端にやっかいになります。祝日データをどこから持ってくるか、振替休日をどう扱うか、会社独自の休業日をどう組み込むか――判定ロジック自体は単純でも、データの持ち方と組み合わせ方で実装の見通しが大きく変わります。この記事では、祝日セットを Set<LocalDate> で受け取り、曜日判定と合わせて「休日かどうか」を返す判定メソッドを Java 標準 API だけで実装します。record による祝日情報の構造化や、Java 21 の switch 式による曜日分岐も紹介します。
使いどころ
請求書の発行日が休日に当たった場合、前営業日に自動で繰り上げる判定ロジックに使う
バッチ処理の実行スケジュールで、休日をスキップするかどうかの分岐条件として利用する
勤怠管理システムで、出勤日が祝日に該当するかを判定し、休日出勤手当の対象かを振り分ける
コード例
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Set;
public class HolidayChecker {
/** 指定日が祝日かどうかを判定する */
public static boolean isHoliday(LocalDate date, Set<LocalDate> holidays) {
return holidays.contains(date);
}
/** 指定日が休日(土曜・日曜・祝日)かどうかを判定する */
public static boolean isNonWorkingDay(LocalDate date, Set<LocalDate> holidays) {
DayOfWeek dow = date.getDayOfWeek();
if (dow == DayOfWeek.SATURDAY || dow == DayOfWeek.SUNDAY) {
return true;
}
return isHoliday(date, holidays);
}
/** 指定日が営業日かどうかを判定する */
public static boolean isBusinessDay(LocalDate date, Set<LocalDate> holidays) {
return !isNonWorkingDay(date, holidays);
}
public static void main(String[] args) {
// 2024年の祝日(一部抜粋)
var holidays = Set.of(
LocalDate.of(2024, 1, 1), // 元日
LocalDate.of(2024, 1, 8), // 成人の日
LocalDate.of(2024, 2, 11), // 建国記念の日
LocalDate.of(2024, 2, 12), // 振替休日
LocalDate.of(2024, 5, 3), // 憲法記念日
LocalDate.of(2024, 5, 4), // みどりの日
LocalDate.of(2024, 5, 5), // こどもの日
LocalDate.of(2024, 5, 6) // 振替休日
);
// 判定サンプル
LocalDate newYear = LocalDate.of(2024, 1, 1); // 元日(祝日)
LocalDate friday = LocalDate.of(2024, 1, 5); // 金曜日(平日)
LocalDate saturday = LocalDate.of(2024, 1, 6); // 土曜日
System.out.println(newYear + " 休日: " + isNonWorkingDay(newYear, holidays)); // true
System.out.println(friday + " 休日: " + isNonWorkingDay(friday, holidays)); // false
System.out.println(saturday + " 休日: " + isNonWorkingDay(saturday, holidays)); // true
// record で祝日名付きの情報を保持する例(Java 16+)
record Holiday(LocalDate date, String name) {}
var holiday = new Holiday(LocalDate.of(2024, 1, 1), "元日");
System.out.println("祝日: " + holiday.date() + " " + holiday.name());
}
}Version Coverage
Set.of() で祝日データを不変セットとして簡潔に初期化できる。record で祝日名と日付のペアを表現すると可読性が上がる。
// Java 17: Set.of() + record で簡潔に表現
var holidays = Set.of(
LocalDate.of(2024, 1, 1),
LocalDate.of(2024, 1, 8),
LocalDate.of(2024, 2, 11)
);
record Holiday(LocalDate date, String name) {}Library Comparison
注意点
祝日セットに振替休日や国民の休日を含めるかどうかは、呼び出し側の責任になる。判定メソッドは渡された Set を信頼するだけなので、データが不完全だと結果も不正確になる
Set.of() は Java 9 以降でのみ使える。Java 8 環境では Collections.unmodifiableSet(new HashSet<>(Arrays.asList(...))) で代替する
土曜を営業日とする会社や、特定曜日が定休日の業種では、DayOfWeek の判定条件をカスタマイズする必要がある。ハードコードせず、除外曜日のセットを引数で受け取る設計が望ましい
祝日データは年ごとに更新が必要。特に春分・秋分は年によって日付が変わるため、固定値だけでは対応できない
FAQ
振替休日は「祝日が日曜に当たる場合」に翌営業日へ移動する制度です。土曜と祝日の重複では振替休日は発生しません。データ側で振替休日を含める運用が安全です。
祝日セットに会社休業日を追加して渡すのが最も簡単です。判定メソッド側は Set の中身を区別しないため、データ側で一本化すれば追加のコード変更は不要です。
年単位で不変なので、起動時やバッチ開始時に1回生成してキャッシュするのが一般的です。HashSet の contains は O(1) のため、セット自体のルックアップは高速です。