やりたいこと
GASのトリガー(時間主導型)は、1時間毎に実行してはくれるものの、何分に実行など細かな設定はできません。なので、決まった時刻に実行するトリガーを別途用意して対応します。
この対応は検索すると色々なところに書かれてはいたのですが、まとめておくと便利そうだったので備忘録として投稿しておきます。
対応
まず毎時00分に実行する場合は、下記のsetNextTriggerを時間主導型のトリガー(1時間おき)にセットします。
const mainTriggerName = "main"; //実行したい関数名。仮にmain()とします;
//===========================================================================================
// 1時間後の00分に次の実行トリガーをセットする(14:30に実行したら15:00にタイマーセット)
// この関数を1時間ごとのトリガーに指定して運用する
//===========================================================================================
function setNextTrigger(){
const time = new Date();
time.setHours(time.getHours() + 1);
time.setMinutes(00);
//過去のトリガーを削除
removeTrigger(mainTriggerName);
ScriptApp.newTrigger(mainTriggerName).timeBased().at(time).create();
}
//===========================================================================================
// トリガーを削除
//===========================================================================================
function removeTrigger(triggerName){
const triggers = ScriptApp.getProjectTriggers();
for(const trigger of triggers){
if(trigger.getHandlerFunction() == triggerName){
ScriptApp.deleteTrigger(trigger);
}
}
}
ただトリガーは分までしか認識しないので、この場合でも0分の0秒ぴったりに実行してくれるわけではありません。
ぴったり実行したい場合は、1分前にトリガーをセットして0秒になるまでSleepが一般的だそうです。
というわけで書き直したものが下記です。
const mainTriggerName = "mainTrigger";
//===========================================================================================
// 59分に次の実行トリガーをセットする(14:30に実行したら14:59にタイマーセット)
// この関数を1時間ごとのトリガーに指定して運用する
//===========================================================================================
function setNextTrigger(){
const time = new Date();
time.setMinutes(59);
//過去のトリガーを削除
removeTrigger(mainTriggerName);
ScriptApp.newTrigger(mainTriggerName).timeBased().at(time).create();
}
//===========================================================================================
// 毎時59分に呼び出されるメイン処理のトリガー
//===========================================================================================
function mainTrigger(){
//トリガーは毎時59分にセットされるため、00分00秒に処理を開始するまで待機
const startTime = new Date();
startTime.setMinutes(startTime.getMinutes() + 1);
startTime.setSeconds(0);
startTime.setMilliseconds(0);
Utilities.sleep(startTime - new Date());
main(); //メイン処理呼び出し。ここでは仮にmain()としています
}
//===========================================================================================
// トリガーを削除
//===========================================================================================
function removeTrigger(triggerName){
const triggers = ScriptApp.getProjectTriggers();
for(const trigger of triggers){
if(trigger.getHandlerFunction() == triggerName){
ScriptApp.deleteTrigger(trigger);
}
}
}
これでmain()が毎時0分0秒に実行されるようセットできました。
ただこの方法だと最長1分近くSleepするため、トリガー実行可能時間6分のうちその分消費しても大丈夫な処理だけに入れることをおすすめします。