「営業日一覧」とは何をするユーティリティか
まずイメージしてほしいのは、カレンダーから「土日と祝日を抜いた日だけ」を抜き出した表です。
請求締め、入金予定表、納期チェック、SLA(何営業日以内に対応)など、業務では「営業日」が基準になることがとても多いです。
営業日一覧ユーティリティは、
「開始日〜終了日のあいだで、“営業日だけ”を順番に並べる」
ための小さな道具です。
ここに「土日を除く」「祝日マスタを除く」といったルールを閉じ込めておくことで、アプリ側のコードをシンプルにできます。
営業日の基本ルールを決める
まずは「土日以外=営業日」という前提から
現実の会社では「土曜も営業」「第2土曜だけ休み」「独自の会社休日」などいろいろありますが、
最初の一歩としては、次のように決めてしまうと分かりやすいです。
平日(月〜金)は営業日
土日(土・日)は休業日
このルールをコードにすると、こうなります。
import java.time.DayOfWeek;
import java.time.LocalDate;
public class BusinessDayRules {
public static boolean isWeekend(LocalDate date) {
DayOfWeek dow = date.getDayOfWeek();
return dow == DayOfWeek.SATURDAY || dow == DayOfWeek.SUNDAY;
}
public static boolean isBusinessDayBasic(LocalDate date) {
return !isWeekend(date);
}
}
Javaここで大事なのは、「営業日かどうかの判定ロジックを1か所に閉じ込める」という発想です。
あちこちで「if (dow == SATURDAY || dow == SUNDAY) …」と書き散らすのではなく、
必ず isBusinessDay を通すようにしておくと、後からルールを変えるのがとても楽になります。
祝日・会社休日を考慮した営業日判定
祝日マスタを持つ、という発想
実務では「土日以外でも休み」が必ず出てきます。
代表例が「祝日」と「会社独自の休日」です。
これをコードに埋め込むのではなく、
「休業日マスタ(祝日・会社休日の一覧)」としてデータで持つのが定石です。
import java.time.LocalDate;
import java.util.Set;
public class BusinessDayRules {
private final Set<LocalDate> holidays;
public BusinessDayRules(Set<LocalDate> holidays) {
this.holidays = holidays;
}
public boolean isBusinessDay(LocalDate date) {
if (isWeekend(date)) {
return false;
}
if (holidays.contains(date)) {
return false;
}
return true;
}
private boolean isWeekend(LocalDate date) {
switch (date.getDayOfWeek()) {
case SATURDAY:
case SUNDAY:
return true;
default:
return false;
}
}
}
Javaここで深掘りしたいポイントは二つです。
営業日判定は「土日か?」「休業日マスタに含まれているか?」の二段階で決める。
祝日や会社休日はコードではなくデータ(Set<LocalDate> など)として持つ。
こうしておくと、「来年の祝日を追加する」「会社独自の休みを増やす」といった変更を、
コード変更なしで対応できるようになります。
営業日一覧を生成する基本ユーティリティ
開始日〜終了日のあいだの営業日だけを列挙する
営業日判定ができたら、あとは「日付範囲を回しながら、営業日だけ拾う」だけです。
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class BusinessDayRange {
private final BusinessDayRules rules;
public BusinessDayRange(BusinessDayRules rules) {
this.rules = rules;
}
public List<LocalDate> businessDaysBetween(LocalDate startInclusive, LocalDate endInclusive) {
if (endInclusive.isBefore(startInclusive)) {
throw new IllegalArgumentException("終了日は開始日以降である必要があります");
}
List<LocalDate> result = new ArrayList<>();
LocalDate d = startInclusive;
while (!d.isAfter(endInclusive)) {
if (rules.isBusinessDay(d)) {
result.add(d);
}
d = d.plusDays(1);
}
return result;
}
}
Java使い方の例です。
import java.time.LocalDate;
import java.util.List;
import java.util.Set;
public class BusinessDayExample {
public static void main(String[] args) {
Set<LocalDate> holidays = Set.of(
LocalDate.of(2025, 1, 1),
LocalDate.of(2025, 1, 13)
);
BusinessDayRules rules = new BusinessDayRules(holidays);
BusinessDayRange range = new BusinessDayRange(rules);
LocalDate start = LocalDate.of(2025, 1, 1);
LocalDate end = LocalDate.of(2025, 1, 15);
List<LocalDate> businessDays = range.businessDaysBetween(start, end);
for (LocalDate d : businessDays) {
System.out.println(d);
}
}
}
Javaここで重要なのは、「営業日判定」と「範囲生成」をクラスで分けていることです。
ルールは BusinessDayRules、範囲生成は BusinessDayRange。
この分離によって、ルールを差し替えたりテストしたりしやすくなります。
「n営業日後」を計算するユーティリティ
営業日一覧の応用:締め日・納期計算
営業日一覧が作れるようになると、次に欲しくなるのが「n営業日後」の計算です。
例えば「受付から3営業日以内に対応」「5営業日後が納期」といった要件です。
import java.time.LocalDate;
public class BusinessDayCalculator {
private final BusinessDayRules rules;
public BusinessDayCalculator(BusinessDayRules rules) {
this.rules = rules;
}
public LocalDate addBusinessDays(LocalDate start, int businessDays) {
if (businessDays < 0) {
throw new IllegalArgumentException("businessDays は 0以上で指定してください");
}
LocalDate d = start;
int count = 0;
while (count < businessDays) {
d = d.plusDays(1);
if (rules.isBusinessDay(d)) {
count++;
}
}
return d;
}
}
Java使い方の例です。
LocalDate today = LocalDate.of(2025, 1, 9); // 木曜と仮定
LocalDate due = calculator.addBusinessDays(today, 3);
System.out.println("3営業日後の期日: " + due);
Javaここで深掘りしたいのは、「カレンダー日数ではなく“営業日数”で数える」という感覚です。
土日や祝日を飛ばしながらカウントするので、
「3日後」ではなく「3営業日後」というビジネスの言葉にそのまま対応できます。
営業日一覧と「月」「年」の組み合わせ
ある月の営業日一覧を作る
「今月の営業日カレンダー」「月次レポートの営業日数」などでよく使うパターンです。
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.List;
public class MonthlyBusinessDays {
private final BusinessDayRange range;
public MonthlyBusinessDays(BusinessDayRange range) {
this.range = range;
}
public List<LocalDate> businessDaysOfMonth(YearMonth ym) {
LocalDate start = ym.atDay(1);
LocalDate end = ym.atEndOfMonth();
return range.businessDaysBetween(start, end);
}
}
Javaこれで、「2025年3月の営業日一覧」のようなものを簡単に取得できます。
月一覧生成ユーティリティと組み合わせれば、「2024年度の各月の営業日数」といった集計も自然に書けます。
セキュリティ・運用の観点から見た営業日一覧
「営業日ルール」をコードにベタ書きしない
営業日一覧は、システムのあちこちで使われる“基準”になります。
ここが間違っていると、請求・入金・納期・SLA など、ビジネスの根幹に影響します。
だからこそ、次のような設計が重要です。
営業日判定ロジックを1か所に集約する(BusinessDayRules のようなクラス)。
祝日・会社休日はコードではなくマスタデータとして管理する。
マスタの更新履歴を残し、「いつ・誰が・どの休業日を追加/変更したか」を追跡できるようにする。
これは単なる便利ユーティリティではなく、「業務ルールの一部」をコード化している、という意識を持ってほしいところです。
範囲が広すぎる要求をそのまま受けない
「2000年〜2100年の営業日一覧を全部出して」といった要求をそのまま受けると、
3万日以上を営業日判定し、リストに詰めることになります。
実務では、例えば次のような制限をユーティリティ側に組み込むことが多いです。
営業日一覧を生成できる最大期間を決める(例:3年分まで)。
それを超える要求が来たら例外にする、あるいは警告ログを出す。
これは、誤設定や悪意ある入力による負荷増大(事実上のDoS)を防ぐための防御線です。
まとめ:営業日一覧ユーティリティで身につけてほしい感覚
営業日一覧ユーティリティは、「開始日〜終了日のあいだで、営業日だけを並べる」だけのシンプルな道具です。
でも、その裏には次のような大事な考え方が隠れています。
営業日判定ロジックを1か所に集約し、土日・祝日・会社休日をそこで判断する。
祝日や会社休日はコードではなくマスタデータとして管理する。
営業日一覧生成と営業日加算(n営業日後)は、同じルールを共有する。
期間の上限を決めて、誤設定や負荷増大を防ぐ。
「営業日」はビジネスルールそのものなので、変更しやすく・追跡しやすい設計にする。
もしあなたのプロジェクトで、
「土日を飛ばす for 文」「祝日を if で個別に除外するコード」があちこちに散らばっているなら、
それを一度、「営業日ルール+営業日一覧ユーティリティ」に集約できないか考えてみてください。
それだけで、コードの意図がはっきりし、
ビジネスルールの変更にも強い、“実務で戦える”日付・時間まわりの設計に近づきます。
