見出し画像

アプリで営業日数を計算する

やりたいこと

Kintoneのアプリで2つの日付の営業日数を表示したい。
例)2023年5月1日から5月10日までの営業日数を自動計算したい。

デモ画面

以下の画面では、2023年5月と9月の大型連休の休日数をJavascriptで計算して、標準機能で計算した日数計算フィールドから休日数を差引して営業日数を求めています。

営業日数の計算

仕組みの考え方

日数計算(両端)の値から休日(土日祝)の日数を引き算して除いた日数を営業日数として計算します。
営業日=日数計算-休日数
日数計算は、Kintoneの標準機能でも実装可能ですが、標準機能では休日判定が出来ないので、休日数の計算は、Javascriptコードを用いたカスタマイズで実装します。

今回は、日付型で開始日と終了日のフィールド、数値型で休日数のフィールド、計算型で日数計算と営業日数のフィールドを作成します。
タイトル(文字列1行)はなくても結構です。

フォームの設計

まず、日数計算(両端)フィールドコードを「日数計算」として、計算式を以下の通り設定します。
IF(終了日<>"",(終了日-開始日)/86400+1,"")

日数計算の式は「終了日-開始日」ですが、Kintoneの日付型フィールドは、秒単位で値を持っているので、計算結果を1日の秒数(60秒×60分×24時間)=86400秒で割り算して、日数にします。
計算式の+1は、開始日から終了日までの日数を両端で計算するためです。
片端計算にしたい場合は、+1の部分を削除して下さい。
IF文で囲っているのは、終了日の値が入力されてから計算を実行する様にするためです。

日数計算の設定

休日数フィールド(数値型)のフィールドコードは「休日数」としてJavascriptコードの初期設定と合わせます。
休日数の計算は、Javascriptコードで行いますので、フィールドコードを設定するだけです。

営業日数のフィールド(計算型)のフィールドコードは「営業日数」として、計算式を以下の通り設定します。
IF(終了日<>"",(日数計算-休日数),"")

IF文で囲っているのは、終了日の値が入力されてから計算を実行する様にするためです。

営業日数の設定

休日数を計算するJavascriptコード

初期設定で、Kintoneアプリの「開始日」「終了日」「休日数」のフィールドコードを設定します。
会社独自の休日設定は、カレンダーに無い休日を設定します。
date:に月/日を、 name:に休日名を必要な数だけ設定してください

/* 指定日付範囲の休日数を計算する処理 */
(function() {
    "use strict";

    // 初期設定:フィールドコード
    const START_DATE_FIELD = '開始日';
    const END_DATE_FIELD = '終了日';
    const HOLIDAY_COUNT_FIELD = '休日数';

    // 会社独自の休日設定
    const customHolidays = [
        { date: '1/2', name: '年末年始休暇' },
        { date: '1/3', name: '年末年始休暇' },
        { date: '12/30', name: '年末年始休暇' },
        { date: '12/31', name: '年末年始休暇' }
    ];

    // 日付を文字列に変換する関数
    function formatDate(date) {
        return (date.getMonth() + 1) + '/' + date.getDate();
    }

    // 休日を判定する関数
    function isHoliday(date) {
        let day = date.getDay();
        let formattedDate = formatDate(date);
        let isCustomHoliday = customHolidays.some(d => d.date === formattedDate);
        return day === 0 || day === 6 || isCustomHoliday || holiday_jp.isHoliday(date);
    }

    // 休日をカウントする関数
    function countHolidays(start, end) {
        let current = new Date(start);
        let endDay = new Date(end);
        let count = 0;

        while (current <= endDay) {
            if (isHoliday(current)) {
                count++;
            }
            current.setDate(current.getDate() + 1);
        }
        return count;
    }

    // イベントハンドラ関数
    function handleEvent(event) {
        let record = event.record;
        record[HOLIDAY_COUNT_FIELD].disabled = true; // 休日数フィールドを編集不可にする

        let start = record[START_DATE_FIELD].value;
        let end = record[END_DATE_FIELD].value;

        if (start && end) {
            record[HOLIDAY_COUNT_FIELD].value = countHolidays(start, end);
        }
        return event;
    }

    // イベントリスナー登録
    kintone.events.on([
        `app.record.create.change.${END_DATE_FIELD}`,
        `app.record.edit.change.${END_DATE_FIELD}`
    ], handleEvent);
})();

カスタムコードは、新規登録画面と編集画面で、終了日フィールドの値が変更されたイベントをトリガーとして動作します。

休日判定には、外部ライブラリの「holiday_jp.js」を使用しています。
これは、引数日付の休日判定と休日名を返す機能があります。
'holiday_jp-js'の公開サイトはこちらです。

初期設定が完了したコードを好きな名前で保存して、holiday_jp.jsとカスタムコードを、アプリの設定>JavaScript / CSSでカスタマイズアプリの設定の画面で以下の通りアップロードします。

Javascriptの設定画面

Javascriptカスタムコードは動作確認済ですので、外部ライブラリの設定と初期設定のフィールドコードさえ正しければ問題なく動作すると思います。
「holiday_jp.js」の入手方法は、以下の記事も参考にしてください。
アプリで入力日付の休日判定と営業日を求めるカスタマイズの紹介です。

よろしければサポートお願いします! いただいたサポートは、note記事制作の活動費に使わせていただきます!