Java Tips | 日付・時間:営業日一覧

Java Java
スポンサーリンク

「営業日一覧」とは何をするユーティリティか

まずイメージしてほしいのは、カレンダーから「土日と祝日を抜いた日だけ」を抜き出した表です。
請求締め、入金予定表、納期チェック、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 で個別に除外するコード」があちこちに散らばっているなら、
それを一度、「営業日ルール+営業日一覧ユーティリティ」に集約できないか考えてみてください。

それだけで、コードの意図がはっきりし、
ビジネスルールの変更にも強い、“実務で戦える”日付・時間まわりの設計に近づきます。

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