首页 > 解决方案 > 如何使用基于时间的触发器每小时运行一个脚本,仅在工作日的每小时运行一次?

问题描述

我只需要在工作日每小时运行一次 Google App Script 脚本。

做两者之一似乎很容易,但将它结合起来我不确定......

每小时触发:ScriptApp.newTrigger("RefreshRates").timeBased().inTimezone("GMT").everyHours(1).nearMinute(0).create();

它需要尽可能接近每小时运行一次。因此,例如 09:00、10:00、11:00 等。我知道 App Script 对此不太准确,但尽可能接近时间。

我发现这可能有助于解决工作日问题,但是否可以将上述内容与以下内容结合起来:

 function createWeeklyTrigger() {
    var days = [ScriptApp.WeekDay.MONDAY, ScriptApp.WeekDay.TUESDAY,
                ScriptApp.WeekDay.WEDNESDAY, ScriptApp.WeekDay.THURSDAY,                                            
                ScriptApp.WeekDay.FRIDAY];
    for (var i=0; i<days.length; i++) {
       ScriptApp.newTrigger("your_function_name")
                .timeBased().onWeekDay(days[i])
                .atHour(11).create();
    }
 }

理想的时间实际上是格林威治标准时间周五晚上 9:45 到周日晚上 10:15,此时外汇市场关闭并开放......

编辑:我想我在最初的问题中对每个工作日的每个小时都做了一些不太清楚的事情,而不是特定的时间。但市场的一周从格林威治标准时间周日 22:00 开始,到格林威治标准时间周五 22:00 结束。因此,理想的时间是从格林威治标准时间周日 22:00 到格林威治标准时间周五 22:00 之间的每个小时……

标签: google-apps-scriptgoogle-sheetstriggers

解决方案


我认为,您最好的选择是将 a 设置为Trigger您希望脚本运行的每个小时,在设置工作日的循环中使用第二个循环,因为everyHours()不接受开始和结束参数。

请注意,这将创建在一周中的同一天触发的单独触发器。

function setWeekdaysTrigger() {

  var startHour = 9;
  var endHour   = 13;
  var daysWeek  = []; //put Enums for days of the week here;

  //set trigger to specific week days;
  daysWeek.forEach(function(day){
    //set trigger for 9AM to 13PM;
    for(var h=startHour; h<endHour; h++) {
      var tg = ScriptApp.newTrigger('doSomething').timeBased();
          tg.onWeekDay(day);
          tg.atHour(h).nearMinute(15).create(); //arbitrary precision (minutes);
    }        
  });

}

作为答案的更新 - 请注意,不幸的是,您可以代表一个用户为项目创建多少触发器(目前等于每个用户每个项目 20 个)有配额。

可配置的触发器

正如评论中所阐明的,配置自定义天数+自定义小时数触发器需要更复杂的处理。建议的解决方案(不计算显式日期时间检查)是动态触发器配置(因为由于重复重复而无法同时设置onWeekDay(day)+ everyHours(n)[我发现onWeekDay(day)设置隐式everyWeeks(1)重复模式]):

首先,创建一个设置天数重复的主触发函数

function custom24trigger() {
  var days  = [ScriptApp.WeekDay.TUESDAY]; //put Enum values here;

  //create trigger for each date (arbitrary hours);
  days.forEach(function(day){
    for(var offset = 0; offset < 23; offset=offset+4) { //every 4 hours;
      var tg = ScriptApp.newTrigger('changeTriggers').timeBased();
          tg.onWeekDay(day).atHour(offset).create(); //change every N hours;
    }
  });

}

其次,创建一个触发器更改函数,该函数将通过设置重复触发,清除先前设置的触发器并创建新的触发器:

function changeTriggers() {
  var triggers   = ScriptApp.getProjectTriggers(); //get project's triggers;
  var props      = PropertiesService.getScriptProperties(); //get script properties store;
  var triggerIds = props.getProperty('triggerIds'); //get arbitrary property to set Ids to;

  //if ids are not empty, split into Array of Ids, else set up empty Array;
  if(triggerIds!==null) { triggerIds = triggerIds.split(','); }else { triggerIds = []; }

  //loop over triggers and delete saved;
  triggerIds.forEach(function(id){
    triggers.forEach(function(trigger){
      if(trigger.getUniqueId() == id) { 
        ScriptApp.deleteTrigger(trigger); 
      }
    });
  });

  var today = new Date(); //current date;
  var start = today.getHours(); //current hour;

  var stop = start+3; //hour to stop (sets N triggers);

  //create hourly trigger for each hour;
  var newId = '';
  for(var h = start; h < stop; h++) {
    var trg = ScriptApp.newTrigger('doSomething').timeBased();

    //make trigger fire once at specific date and hour;
    today.setHours(h);
    today.setMinutes(0);

    var created = trg.at(today).create();   
    newId += ','+created.getUniqueId(); //get new trigger Id;
  }

  props.setProperty('triggerIds', newId); //set trigger property;
}

推荐阅读