見出し画像

土日祝日を除いた正確な営業日計算を行うJavaScript関数

概要

このコードは、日本の土日祝日を考慮した上で、次の営業日を計算するためのJavaScript関数を提供します。
特定の日から指定した日数後の営業日を計算し、例えば「翌営業日」「翌々営業日」を求めたいときに使用できます。
祝日は毎年自動的に計算されるため、毎年更新する必要はありません。

使用方法

  1. getHolidays(year)

    • 指定された年の祝日リストを生成します。

    • 祝日は自動的に計算されるため、年次更新の必要がありません。

  1. getNextBusinessDay(date, daysToAdd)

    • dateで指定された日付から、土日および祝日を除いた次の営業日を求める関数です。daysToAddで何営業日後かを指定します。

    • 例えば、daysToAddに1を指定すると「翌営業日」、2を指定すると「翌々営業日」が計算されます。

実用例

例えば、特定の日付から1営業日後や2営業日後の営業日を取得したい場合に、以下のように使用します。

実用例1: 翌営業日を計算する

const today = new Date();
const nextBusinessDay = getNextBusinessDay(today, 1); // 翌営業日
console.log(`翌営業日: ${nextBusinessDay}`);

この例では、today(今日の日付)から土日祝日を除いた翌営業日が計算されます。
例えば、金曜日に実行すると、翌営業日は次の月曜日(祝日でない場合)になります。

実用例2: 翌々営業日を計算する

const today = new Date();
const secondBusinessDay = getNextBusinessDay(today, 2); // 翌々営業日
console.log(`翌々営業日: ${secondBusinessDay}`);

この例では、今日から2営業日後の営業日が計算されます。
例えば、木曜日に実行すると、翌々営業日は次週の火曜日(祝日でない場合)になる可能性があります。

解説

getHolidays(year)

日本の主要な祝日(元日、成人の日、天皇誕生日など)をリスト化します。
動的な祝日(春分の日、秋分の日、体育の日など)も自動計算されるため、毎年の変更に対応しています。
この関数は内部で使用され、指定した年の祝日をリストとして返します。

getNthWeekdayOfMonth(year, month, nth, weekday)

例えば、成人の日や敬老の日のように「〇月の第〇月曜日」を特定するための関数です。
指定された月の第〇月曜日や第〇金曜日などを計算するのに使用されます。

getVernalEquinoxDay(year) と getAutumnEquinoxDay(year)

春分の日と秋分の日は、年によって日付が異なりますが、これらを概算で計算するための関数です。

isHoliday(date, holidays)

この関数は、渡された日付が祝日リストに含まれているかを確認し、祝日であればtrueを返します。
これにより、祝日を除外するロジックを組み込むことができます。

getNextBusinessDay(date, daysToAdd)

指定された日付から、土日と祝日を除いた次の営業日を計算するメイン関数です。
日付を1日ずつ進めながら、土曜日、日曜日、祝日をスキップし、指定された営業日数分だけ進んだ日を返します。
この関数を使うことで、土日や祝日を含まない正確な営業日計算ができます。

実際の活用シーン

  • 納期管理: 土日祝日を除いた「〇営業日後の納期」を正確に計算し、顧客に伝えることができます。

  • イベント計画: イベントやプロジェクトのスケジュールを組む際に、土日祝日を除いて計画するためのツールとして利用できます。

まとめ

このコードを使えば、日本の土日祝日を考慮した営業日計算が自動で行えます。
例えば、納期の管理や取引日の計算など、ビジネスシーンで役立つ場面がたくさんあります。
特に祝日が毎年変わるため、手動での更新を不要にして自動計算を取り入れることが可能です。

// 祝日を自動計算する関数
function getHolidays(year) {
    return [
        new Date(year, 0, 1), // 元日 (1月1日)
        getNthWeekdayOfMonth(year, 1, 2, 1), // 成人の日 (1月第2月曜日)
        new Date(year, 2, 11), // 建国記念の日 (2月11日)
        new Date(year, 2, 23), // 天皇誕生日 (2月23日)
        getVernalEquinoxDay(year), // 春分の日 (年による)
        new Date(year, 3, 29), // 昭和の日 (4月29日)
        new Date(year, 4, 3), // 憲法記念日 (5月3日)
        new Date(year, 4, 4), // みどりの日 (5月4日)
        new Date(year, 4, 5), // こどもの日 (5月5日)
        getNthWeekdayOfMonth(year, 7, 3, 1), // 海の日 (7月第3月曜日)
        getNthWeekdayOfMonth(year, 8, 2, 1), // 敬老の日 (9月第3月曜日)
        getAutumnEquinoxDay(year), // 秋分の日 (年による)
        getNthWeekdayOfMonth(year, 9, 2, 1), // 体育の日 (10月第2月曜日)
        new Date(year, 10, 3), // 文化の日 (11月3日)
        new Date(year, 10, 23) // 勤労感謝の日 (11月23日)
    ];
}

// 月の第X月曜日を取得する関数(成人の日、海の日、敬老の日、体育の日に使用)
function getNthWeekdayOfMonth(year, month, nth, weekday) {
    let date = new Date(year, month, 1);
    let count = 0;
    while (date.getDay() !== weekday || ++count < nth) {
        date.setDate(date.getDate() + 1);
    }
    return date;
}

// 春分の日を取得する関数(概算)
function getVernalEquinoxDay(year) {
    const day = Math.floor(20.8431 + 0.242194 * (year - 1980)) - Math.floor((year - 1980) / 4);
    return new Date(year, 2, day);
}

// 秋分の日を取得する関数(概算)
function getAutumnEquinoxDay(year) {
    const day = Math.floor(23.2488 + 0.242194 * (year - 1980)) - Math.floor((year - 1980) / 4);
    return new Date(year, 8, day);
}

// 祝日かどうかを判定する関数
function isHoliday(date, holidays) {
    return holidays.some(holiday => 
        date.getFullYear() === holiday.getFullYear() &&
        date.getMonth() === holiday.getMonth() &&
        date.getDate() === holiday.getDate()
    );
}

// 土日祝日を省くための関数
function getNextBusinessDay(date, daysToAdd) {
    let nextDay = new Date(date);
    let addedDays = 0;
    const holidays = getHolidays(nextDay.getFullYear()); // 当年の祝日を取得

    // 指定された日数分、土日祝日を除く営業日をカウント
    while (addedDays < daysToAdd) {
        nextDay.setDate(nextDay.getDate() + 1); // 翌日を設定
        if (nextDay.getDay() !== 0 && nextDay.getDay() !== 6 && !isHoliday(nextDay, holidays)) {
            addedDays++; // 土日祝日でない場合のみカウント
        }
    }

    return nextDay;
}

いいなと思ったら応援しよう!