営業日判定のゴールイメージ
「この日付は営業日か?」「締切日が休業日のときは翌営業日にずらしたい」
業務システムでは、こういう“営業日判定”が本当に頻繁に出てきます。
ここで大事なのは、
営業日=「土日以外」では終わらないことが多い、という現実です。
祝日・会社独自の休業日・年末年始など、現場ごとにルールが違います。
だからこそ、
「営業日判定のロジックを一か所に閉じ込める」
「曜日判定と祝日判定を分けて考える」
この二つを意識して設計するのが、とても重要になります。
最小構成:土日以外を営業日とみなす
DayOfWeek を使ったシンプルな営業日判定
まずは「土日以外は営業日」という、最小限のパターンから始めます。
import java.time.DayOfWeek;
import java.time.LocalDate;
public class SimpleBusinessDay {
public static void main(String[] args) {
LocalDate date1 = LocalDate.of(2025, 3, 28); // 金
LocalDate date2 = LocalDate.of(2025, 3, 29); // 土
System.out.println(date1 + " は営業日? " + isBusinessDay(date1)); // true
System.out.println(date2 + " は営業日? " + isBusinessDay(date2)); // false
}
public static boolean isBusinessDay(LocalDate date) {
DayOfWeek dow = date.getDayOfWeek();
return dow != DayOfWeek.SATURDAY && dow != DayOfWeek.SUNDAY;
}
}
Javaここで一番大事なのは、
「営業日判定を isBusinessDay(LocalDate) というメソッドに閉じ込めた」ことです。
この一手間で、
「あとから祝日を考慮したくなった」「土曜も営業に変わった」
といった仕様変更に、かなり強くなります。
祝日・会社休業日を考慮した営業日判定
祝日リストを持たせて判定する
現実の業務では、「土日+祝日+会社独自の休業日」を休みとしたいことが多いです。
ここでは、簡単のために「祝日を LocalDate の集合として持つ」パターンを示します。
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;
public class BusinessDayWithHolidays {
private final Set<LocalDate> holidays = new HashSet<>();
public BusinessDayWithHolidays(Set<LocalDate> holidays) {
this.holidays.addAll(holidays);
}
public boolean isBusinessDay(LocalDate date) {
DayOfWeek dow = date.getDayOfWeek();
if (dow == DayOfWeek.SATURDAY || dow == DayOfWeek.SUNDAY) {
return false;
}
if (holidays.contains(date)) {
return false;
}
return true;
}
public static void main(String[] args) {
Set<LocalDate> holidays = new HashSet<>();
holidays.add(LocalDate.of(2025, 1, 1)); // 元日
holidays.add(LocalDate.of(2025, 1, 2)); // 会社休業日
holidays.add(LocalDate.of(2025, 1, 3)); // 会社休業日
BusinessDayWithHolidays checker = new BusinessDayWithHolidays(holidays);
LocalDate d1 = LocalDate.of(2025, 1, 1); // 祝日
LocalDate d2 = LocalDate.of(2025, 1, 4); // 土曜
LocalDate d3 = LocalDate.of(2025, 1, 6); // 月曜
System.out.println(d1 + " 営業日? " + checker.isBusinessDay(d1)); // false
System.out.println(d2 + " 営業日? " + checker.isBusinessDay(d2)); // false
System.out.println(d3 + " 営業日? " + checker.isBusinessDay(d3)); // true
}
}
Javaここで深掘りしたいポイントは二つです。
一つ目は、
「曜日判定」と「祝日判定」を分けて書いていること。
これにより、「土曜も営業にしたい」「祝日は別マスタにしたい」といった変更がしやすくなります。
二つ目は、
「祝日情報を外から注入できるようにしている」こと。
コンストラクタで Set<LocalDate> を受け取るようにしておけば、
DB・設定ファイル・外部 API など、どこからでも祝日情報を持ってこられます。
営業日を使った「次の営業日」計算
営業日でない場合に、翌営業日にずらす
よくある要件に、
「締切日が休業日の場合は、翌営業日に繰り延べる」があります。
import java.time.LocalDate;
import java.util.Set;
public class NextBusinessDayExample {
public static void main(String[] args) {
Set<LocalDate> holidays = Set.of(
LocalDate.of(2025, 1, 1),
LocalDate.of(2025, 1, 2),
LocalDate.of(2025, 1, 3)
);
BusinessDayWithHolidays checker = new BusinessDayWithHolidays(holidays);
LocalDate due = LocalDate.of(2025, 1, 4); // 土曜
LocalDate nextBusiness = nextBusinessDay(due, checker);
System.out.println("締切日 : " + due); // 2025-01-04
System.out.println("実際の締切日 : " + nextBusiness); // 2025-01-06
}
public static LocalDate nextBusinessDay(LocalDate date, BusinessDayWithHolidays checker) {
LocalDate d = date;
while (!checker.isBusinessDay(d)) {
d = d.plusDays(1);
}
return d;
}
}
Javaここでの重要ポイントは、
「営業日判定ロジックを再利用して、“次の営業日”も表現している」ことです。
isBusinessDay を一か所に閉じ込めておけば、
「翌営業日」「前営業日」「N 営業日後」などのロジックも、
すべてその上に積み上げることができます。
N 営業日後を求める
「3 営業日後」などの計算
例えば「入金確認から 3 営業日後に発送する」といった要件です。
import java.time.LocalDate;
import java.util.Set;
public class NBusinessDaysLaterExample {
public static void main(String[] args) {
Set<LocalDate> holidays = Set.of(
LocalDate.of(2025, 1, 1),
LocalDate.of(2025, 1, 2),
LocalDate.of(2025, 1, 3)
);
BusinessDayWithHolidays checker = new BusinessDayWithHolidays(holidays);
LocalDate base = LocalDate.of(2025, 1, 6); // 月曜
LocalDate after3 = plusBusinessDays(base, 3, checker);
System.out.println("基準日 : " + base); // 2025-01-06
System.out.println("3営業日後 : " + after3); // 2025-01-09
}
public static LocalDate plusBusinessDays(LocalDate base, int n, BusinessDayWithHolidays checker) {
LocalDate d = base;
int count = 0;
while (count < n) {
d = d.plusDays(1);
if (checker.isBusinessDay(d)) {
count++;
}
}
return d;
}
}
Javaここで深掘りしたいのは、
「営業日という概念は“日数”ではなく“カレンダー+ルール”で決まる」という点です。
単純に plusDays(3) ではなく、
「1 日ずつ進めながら、営業日だけをカウントする」という発想が必要になります。
設計のコツ:営業日判定を“ドメインの中心”に置く
isBusinessDay(LocalDate) を“真ん中”に置く
営業日判定は、
締切日、発送日、入金日、バッチ実行日など、
システムのあらゆるところに顔を出します。
だからこそ、
「営業日かどうか」を判定するメソッドを、ドメインの中心に置く
という設計がとても効いてきます。
例えば、こんなインターフェースを切っておくイメージです。
public interface BusinessCalendar {
boolean isBusinessDay(LocalDate date);
LocalDate nextBusinessDay(LocalDate date);
LocalDate previousBusinessDay(LocalDate date);
LocalDate plusBusinessDays(LocalDate base, int n);
}
Java実装クラスの中で、
曜日・祝日・会社休業日・特別営業日(祝日だけど営業する日)などをすべて吸収してしまえば、
業務ロジック側は「営業日」という概念だけを意識すればよくなります。
まとめ:営業日判定で絶対に覚えてほしいこと
営業日判定は、「カレンダー+会社ルール」をコードに落とし込む作業です。
曜日判定には DayOfWeek を使う。
祝日・会社休業日は Set<LocalDate> やマスタテーブルとして外出しする。isBusinessDay(LocalDate) を一か所に閉じ込めて、そこを“真ん中”に据える。
「翌営業日」「N 営業日後」は、営業日判定を使って 1 日ずつ進めるイメージで実装する。
もしあなたのコードのどこかに、
「土日だけ if で除外している」「祝日判定が画面ごとにバラバラに書かれている」
といった箇所があれば、
そこを一度「営業日カレンダー」という一つのユーティリティに集約できないか眺めてみてください。
それができたとき、
あなたのシステムは“時間とカレンダーに強い”方向へ、ぐっと近づきます。
