讃岐小僧のEngineering×Techメモ

プログラミングや、趣味の野球、資産運用について、その他、ビジネスやテクノロジーをテーマに様々なことをつぶやく場所です。

【node.js】node-cronで定期実行しているモジュールを祝日を避けて実行する

f:id:keisuke8925gdk:20220111211704p:plain ついに進撃の巨人のファイナルパート2がはじまりました。
楽しみにしていたので、毎週待てなくて大変です。

そんな話は置いておいて、今回の記事は、node-cronで実装している定期実行処理を祝日に実行させないようにするための対応について書いていきたいと思います。

node-cronの基本的な動作のさせ方についてはこちらのリンクを参考にされるといいと思います。

qiita.com

私の会社では、毎日出退勤時に勤怠管理システムで打刻をしなければなりません。

打刻忘れを防ぐために平日の定時にLINEWORKSで打刻を促すメッセージを送っています。

f:id:keisuke8925gdk:20220111204142p:plain

ただし、このBOTですが祝日にも実行されてしまうため何となくストレスを感じてしまします。そのため、祝日に実行されないようにアップデートしていきましょう。

実行環境

  • heroku
  • node.js v16.13.1

祝日のjsonファイルを作成する

まずは下記の通り、holidays.jsonを作成してプロジェクトに設置します。

{
    "holidays": [
        {
            "date": "2022-01-01",
            "name": "元日"
        },
        {
            "date": "2022-01-10",
            "name": "成人の日"
        },
        {
            "date": "2022-02-11",
            "name": "建国記念の日"
        },
        {
            "date": "2022-02-23",
            "name": "天皇誕生日"
        },
        {
            "date": "2022-03-21",
            "name": "春分の日"
        },
        {
            "date": "2022-04-29",
            "name": "昭和の日"
        },
        {
            "date": "2022-05-03",
            "name": "憲法記念日"
        },
        {
            "date": "2022-05-04",
            "name": "緑の日"
        },
        {
            "date": "2022-05-05",
            "name": "こどもの日"
        },
        {
            "date": "2022-07-18",
            "name": "海の日"
        },
        {
            "date": "2022-08-11",
            "name": "山の日"
        },
        {
            "date": "2022-09-19",
            "name": "敬老の日"
        },
        {
            "date": "2022-09-23",
            "name": "秋分の日"
        },
        {
            "date": "2022-10-10",
            "name": "スポーツの日"
        },
        {
            "date": "2022-11-03",
            "name": "文化の日"
        },
        {
            "date": "2022-11-23",
            "name": "勤労感謝の日"
        }
    ]
  }

BOTの実行タイミングが祝日かどうかを判定する

モジュールファイル(check-holiday.js)を作成します。
細かい説明を省きますが、holidays.jsonファイルを読み込み、実行タイミングの日付が、jsonファイル内にリストされている、祝日に該当するのかどうかを確認する機能です。

こちらは、調べていると別のモジュールも存在しており、それらを活用することでさらにスマートに機能を実装できそうでしたが、実際には会社・学校の創立記念日のような国民の祝日に該当しないような祝日や、年末年始(2021年であれば大体の方が28日くらいから休みだったはず、、)などの祝日が以外のイレギュラーケースに対応ができないためわざわざファイルで読み込む形式にしております。

そのため、国民の祝日や利用者に応じた実行させたくない日付を"yyyy-mm-dd"の形式で追記すれば、その日にはBOTが動作しないようになりますのでご利用ください。

const fs = require('fs');
module.exports = function checkHoliday() {

    const jsonObject = JSON.parse(fs.readFileSync('holidays.json', 'utf8'));
    const holidaysArray = jsonObject.holidays
    const result = [];

    holidaysArray.forEach((obj) => {
        result.push(obj.date)
    });

    const today = new Date();
    /** 文字列に日付をフォーマットする */
    const formatted = `${today.getFullYear()}-${(today.getMonth()+1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`.replace(/\n|\r/g, '');


    if(result.includes(formatted)){
        return false
    } else {
        return true
    }
}

cron実行時にモジュールを動作させる

index.js等にcheck-holiday.jsを読み込んで利用できるようにして、cronを実行する関数の中で実行します。

※普段利用している独自のモジュール名が混ざっておりますが、ご容赦ください。

/* モジュールの読み込み */
const checkHoliday = require("./check-holiday");

// 定時に特定のメッセージを送付する
cron.schedule('0 0 18 * * 1-5', () => {
    /* 祝日に該当するかチェック */
    const action = checkHoliday()
    if (action) {
        getJWT(jwttoken => {
            getServerToken(jwttoken, newtoken => {
                SendToDepartment(newtoken);
            })
        })
    }},
    {
    scheduled: true,
    timeZone: 'Asia/Tokyo',
});

以上でした。