MENU

【GAS】時間主導型のトリガー イベント オブジェクトを使いこなす

  • URLをコピーしました!

こんにちは etau です 🤓

「時間主導型」のトリガーといえば Google Apps Script の真骨頂と言っても過言ではありません。

このトリガーは PC が立ち上がってない状況でも、指定した時間や定期的に実行できる、GAS の中で大好きな機能の 1 つです。

この時間型トリガーで 1 点だけトリガーの実行時の正確な日時を取得することに苦慮していました。

最近まで gs ファイルの早い段階で const date = new Date(); を宣言して、その変数を取りまわすなど、いろいろと工夫をこらしていました。

今回、時間主導型のトリガー イベント オブジェクトを利用して、そこから取得する方法に変更しました。

調べ物に付き合ってくれた Masayosi Kataoka さん、ありがとう!🤓

また、記事後半では「オブジェクト指向プログラミングでコードを書く理由」にしたがって、便利な機能をクラス化していきます。

目次

イベント オブジェクトを取得するための準備

myFunction というテスト用の関数を作成します。

テスト関数 myFunction

仮引数としてイベント オブジェクトの e を受け取り、ログ出力する関数です。

function myFunction(e) {
  console.log(e);
}

そして、この関数に対してトリガーを設定します。

トリガーの設定

時間主導型トリガーの イベント オブジェクト をとるためには、myFunction 関数に対して以下のように「イベントソースを選択: 時間主導型」「時間ベースのトリガーのタイプを選択: 分ベースのタイマー」「時間の間隔を選択 (分): 1 分おき」と設定します。

時間主導型 分ベースのタイマー 1 分おき トリガー設定

今回はすぐに実行するために、「1 分おき」を選択しています

トリガーを設定した状態で 1 分待ちましょう。

「実行数」を選択すると関数 myFunctionが実行されたことが確認できます。

実行数からログの確認 – 1

つづいてログを確認してみましょう。

トリガーイベントの内容

{ month: 2,
  'day-of-week': 4,
  authMode: 
   { toString: [Function: toString],
     name: [Function: toString],
     toJSON: [Function: toString],
     ordinal: [Function: ordinal],
     compareTo: [Function: compareTo],
     NONE: 
      { toString: [Function: toString],
        name: [Function: toString],
        toJSON: [Function: toString],
        ordinal: [Function: ordinal],
        compareTo: [Function: compareTo],
        NONE: [Circular],
        CUSTOM_FUNCTION: [Object],
        LIMITED: [Object],
        FULL: [Circular] },
     CUSTOM_FUNCTION: 
      { toString: [Function: toString],
        name: [Function: toString],
        toJSON: [Function: toString],
        ordinal: [Function: ordinal],
        compareTo: [Function: compareTo],
        NONE: [Object],
        CUSTOM_FUNCTION: [Circular],
        LIMITED: [Object],
        FULL: [Circular] },
     LIMITED: 
      { toString: [Function: toString],
        name: [Function: toString],
        toJSON: [Function: toString],
        ordinal: [Function: ordinal],
        compareTo: [Function: compareTo],
        NONE: [Object],
        CUSTOM_FUNCTION: [Object],
        LIMITED: [Circular],
        FULL: [Circular] },
     FULL: [Circular] },
  'day-of-month': 10,
  timezone: 'UTC',
  'week-of-year': 6,
  minute: 30,
  hour: 2,
  second: 8,
  year: 2022,
  triggerUid: '10038277' }

今回メインとなるオブジェクト部分をとりだして確認していきます。

今回利用するオブジェクトの内容

今回は authMode, triggerUid プロパティ部分は利用しませんので、必要なものだけピックアップします。

{ month: 2,
  'day-of-week': 4,
  'day-of-month': 10,
  timezone: 'UTC',
  'week-of-year': 6,
  minute: 30,
  hour: 2,
  second: 8,
  year: 2022 }

このオブジェクトの内容を確認していきましょう。

取り出したオブジェクトには、以下のプロパティが設定されています。

プロパティ
timezoneタイムゾーン (UTC しか取得できないため、これ以外の項目があるか不明)
yaer年の値 (4 桁)
month月の値 (1 – 12)
day-of-month日の値 (1 – 31)
hour時間の値 (0 – 23)
minute分の値 (0 – 59)
second秒の値 (0 – 59)
week-of-yearその年の週数の値 (1 – 52)
day-of-week曜日の値 (月曜日: 1, 火曜日: 2, …, 日曜日: 7)
時間主導型トリガーのイベント オブジェクトの内容

ハイフンを含むプロパティは、ブラケット記法で取得する必要があります

日時に関する情報がびっしり詰まってますね。

今回は使いませんが week-of-yearday-of-week なんてプロパティがあるのには、驚きました。

また、Date オブジェクトと値の異なる monthday-of-weekのあつかいには注意が必要です。

さて、目的であるトリガーが実行された日時を返す関数を作っていきます。

イベント オブジェクトから実行時間を取得する関数 getDate

さきほど確認した、プロパティから Date オブジェクトを作って返す関数 getDate を作っていきます。

function myFunction(e) {
  const date = getDate(e);
  console.log(date);
}

/**
 * 時間主導型のトリガー イベント オブジェクトから、トリガーが実行された日時を取得する関数
 * @param {Object} e - 時間主導型のトリガー イベント オブジェクト
 * @return {Date} トリガーが実行された日時の Date オブジェクト
 */
function getDate(e) {
  const date = new Date(
    e.year,
    e.month - 1,
    e['day-of-month'],
    e.hour,
    e.minute,
    e.second
  );
  return date;
}

実行した結果のログを確認していきましょう。

ログの確認方法は、同様に [実行数] から [myFunction] をクリックすることで確認できます

実行数からログの確認 – 2

開始時間とデバッグで表示されている時間を比較すると、9 時間のズレがあります。

実行数からログの確認 – 3

timezone プロパティの値を確認すると UTC のため、このような状況になっています。

timezone プロパティが JST のイベント オブジェクト取得できればとりまわしが楽なので、appsscript.json の設定やトリガー設定時のパラメーターを変更して試してみましたが、UTC 以外の値の取得はできませんでした

では、実際に利用したい JST 環境の実行時間を取得するメソッドを組み込んだクラスを作成していきます。

クラス化

実装するクラスのメンバー (プロパティとメソッド) について、かんたんに解説します。

メンバーの設定

メンバー種別メンバー名メンバーの内容
プロパティtimezoneタイムゾーン (UTC しか取得できないため、これ以外の項目があるか不明)
プロパティyaer年の値 (4 桁)
プロパティmonth月の値 (1 – 12)
プロパティdate日の値 (1 – 31)
プロパティhours時間の値 (0 – 23)
プロパティminutes分の値 (0 – 59)
プロパティseconds秒の値 (0 – 59)
メソッドgetLocaleDate現地時間を取得するメソッド
メソッドgetDateイベント オブジェクトから取得したトリガー実行日時を取得するメソッド
TriggerTimeEvents のメンバー

プロパティの数は多くなりましたが、各項目を判定材料に使いそうなので、お許しください。

すべてをプロパティに設定する必要がなければ、利用する値だけを設定してください。

TriggerTimeEvents クラスのコード

前述のメンバーをクラスに設定していきます。

class TriggerTimeEvents {

  /**
   * 時間主導型のトリガー イベントに関するコンストラクタ
   * @constructor
   * @param {Object} e - 時間主導型のトリガー イベント オブジェクト
   */
  constructor(e) {
    /** @type {number} */
    this.year = e.year;
    /** @type {number} */
    this.month = e.month;
    /** @type {number} */
    this.date = e['day-of-month'];
    /** @type {number} */
    this.hour = e.hour;
    /** @type {number} */
    this.minute = e.minute;
    /** @type {number} */
    this.second = e.second;
    /** @type {string} NOTE: UTC 以外の値が取れるか不明 */
    this.timezone = e.timezone;
  }

  /**
   * 現地時間を取得するメソッド
   * @param {number} diffHours - 時差
   * @return {Date} 時差を調整した日時
   * NOTE: this.timezone が UTC でない場合 (JST であると仮定した) の処理あり
   */
  getLocaleDate(diffHours = 9) {
    if (this.timezone !== 'UTC') return this.getDate();
    const date = this.getDate();
    date.setHours(date.getHours() + diffHours);
    return date;
  }

  /**
   * 時間主導型のトリガーが実行された時間を取得するメソッド
   * @return {Date} 時間主導型のトリガーが実行された日時
   * NOTE: 確認されている状況では UTC の値が設定されている
   */
  getDate() {
    const date = new Date(
      this.year,
      this.month - 1,
      this.date,
      this.hour,
      this.minute,
      this.second
    );
    return date;
  }
}

getLocaleDate メソッドについては timezone プロパティの値が UTC 以外の場合は、JST が取得できる前提でコードを実装しています

呼び出し側の関数で getLocaleDate メソッドで正しく値が取得されているかを確認します。

function myFunction(e) {
  const tte = new TriggerTimeEvents(e);
  console.log(tte.getLocaleDate());
}
実行数からログの確認 – 4

目的の日時の値が無事取得できています。

GitHub リンク

GitHub
GitHub - FrontWorks-Inc/blog_gas-spreadsheet-trigger-time-event-object: create repository create repository. Contribute to FrontWorks-Inc/blog_gas-spreadsheet-trigger-time-event-object development by creating an account on GitHub.

まとめ

今回は、時間主導型トリガーのイベント オブジェクトから正確な実行日時を取得するためのコードを書いて、クラス化していきました。

このコードを書くきっかけになった時間主導型トリガー「特定の日時」を使ったプログラムについて説明します。

時間主導型トリガー「特定の日時」の設定をある日の「12:00」ピッタリに設定しておくと、その時間にトリガーが実行されます。

問題がおこったプログラムの内容は、スプレッドシートの特定列を参照し、同日同時刻の表記のあるメッセージをチャット ツールにリマインダーとして送信するというものでした。

ある日送られてくるはずのリマインダーの通知がないことに気づき、トリガーの設定とコードを調べましたが、どちらも問題なくエラーも確認できませんでした。

ログから開始時間を確認すると「12:00:59」に実行されていました。

ここからは仮定の話ですが、コードの日時の値を取得するタイミングですでに 12:01 に切り替わっていて、スプレッドシートの同日同時刻を参照して、同じ値がないためリマインダーの通知がされていなかったんでしょう。

こんなことがあり、早いタイミングで日時の値を取得するコードで対処していましたが、それでも上記の状態が再現するのではと、また別の回避用のコードを書き足したりしていました。

今回の実行時間ぴったりの値を取得するこの方法によって、今後はスッキリと対応できると思います。

テスト コードを実行された方は、毎分トリガーの削除をお忘れなく。

gas-spreadsheet-trigger-time-event-object_featured-image

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

株式会社フロント・ワークス代表取締役の etau です 🤓
世界一かっこいい GAS を書くために、会社そっちのけで日々精進しています。

へーしゃは「ノンプロ協会」に、個人では「ノンプロ研」所属しています。
趣味は「OOP」「マンガ」「料理 (特にスパイス カレー)」「お酒」「コーヒー」です。

目次
閉じる