土日は通知されたくない! 平日・営業日だけ動く GAS (Google Apps Script) を作る

Slack 通知を伴う GAS は土日祝日に動作して欲しくないですよね! そのようなコードを書いてみました。
2020.01.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

TL; DR

  • 時間主導型トリガーには曜日の概念はありません
  • GAS に書けばよくね?
  • せっかくだし、祝日カレンダーも見るようにした
  • サンプルコード付き

前置き

昨年のことです。
とある作業の進捗を記載しているチーム共有の Google スプレッドシートがあって、このシート記載内容のサマリを毎朝 Slack に通知するようにしていたのですが、そのチームメンバーからこんな指摘がありました。

至極もっともな意見なのですが問題がありました。

  • 該当の仕組みは GAS (Google Apps Script) で記述している
  • そのトリガーとして「時間主導型」>「日付ベースのタイマー」を利用し、毎日決まった時間ウィンドウ内に実行されるようにしていた
  • その設定に、特に曜日の概念はない

つまり、設定だけでホイホイできてしまう類いのものではなかったのでした。
とはいえ土日の話だけではなく、年末年始の長期の休みに Slack に未読がたまり続けるのは精神衛生上よろしくありません。要は GAS が起動しても、肝心の通知ロジックが動作しなければいいということで、社内の知恵袋の力を借りつつ下記のロジックを追加しました。

  1. 起動した日の日時情報を取得する
  2. 曜日が土日であれば、何もせずに終了
  3. 特定のカレンダー(祝日カレンダー、社内公休カレンダー)を参照し、何かしら予定が入っている日であれば同じく終了
  4. 以上の条件にマッチしなければ、営業日と判断する(通知ロジック実行)

この年末年始で正常動作が確認できたので、この場に共有しておきたいと思います。

サンプルコード

要点をしぼってコードを抜き出すと↓のようになりました。
大まかな流れとしては、

  • 今日が営業日かどうかを判定する関数 isWorkday () を作る
  • メイン関数から呼び出して、true が返ってきたらメイン処理実行

という感じです。

// 指定された日が営業日か(営業日 = 「土日でない」「祝日カレンダーに予定がない」)
// 営業日 = true
function isWorkday (targetDate) {

  // targetDate の曜日を確認、週末は休む (false)
  var rest_or_work = ["REST","mon","tue","wed","thu","fri","REST"]; // 日〜土
  if ( rest_or_work [targetDate.getDay ()] == "REST" ) {
    return false;
  }; 

  // 祝日カレンダーを確認する
  var calJpHolidayUrl = "ja.japanese#holiday@group.v.calendar.google.com";
  var calJpHoliday = CalendarApp.getCalendarById (calJpHolidayUrl);
  if (calJpHoliday.getEventsForDay (targetDate).length != 0) {
    // その日に予定がなにか入っている = 祝祭日 = 営業日じゃない (false)
    return false;
  } ;

  // 全て当てはまらなければ営業日 (True)
  return true;
}

// main
function main () {

  var today = new Date ();

  // debug のために任意の日付を仕込む (year,month-1,day,hour,min,sec)
  //today = new Date (2019, 10, 4, 10, 0, 0);

  // 営業日であれば実行
  if (isWorkday (today) == true) {
    // ....
  }
}
  • 5 行目〜9 行目 : 曜日による判定
    • .getDay () すると曜日が数値(0 = 日、1 = 月 ...)で取得できます。
      土日 = 0 と 6 が返ってきたら休みなのですが、数字だと分かりにくいので、曜日分の配列を用意して土日を REST とし、それが返ってきたら休みの日(false)と返すようにしています。
  • 11 行目〜17 行目 : 祝日カレンダーを参照しての判定
    • 「日本の祝日」共有カレンダーは、祝祭日の日に予定として祝祭日名がはいっています。あるカレンダーに対して.getEventsForDay ()すると、その日の予定が配列の形で得られるため、何かしら予定がはいっていたら(.length != 0なら)休みの日(false)と返すようにしています。
  • 28 行目、29 行目 : デバッグ用
    • 挙動を確認するために土日に働いたり祝日になるまで待ったりしたくないので、日付データを上書きして動作確認するためのものです。普段はコメントアウトしてます。
      もし 2019/11/4 を試験したい場合は、コメントの内容のようにnew Date (2019, 10, 4, 10, 0, 0);と指定します(11 月は10と指定)

実際に使っているコードでは、祝日カレンダーともうひとつ、社内の公休カレンダー(年末年始などの予定がはいっているもの)も参照して判断するようにしています。
また随所にLogger.log ()いれたりもしてますが、サンプルコードでは削除しています。

なお念のためですが、このスクリプトを実行する際には「Google カレンダーへのアクセス」を許可してやる必要があります。聞いてきたら許可してあげてください。

まとめ

GAS の定期実行時に、土日や祝日には動作しないような実装をご紹介しました。
もし同様の事象で困っているかたがおられましたら、参考にしてみてください!

参考