Petrus
Petrus

Reputation: 321

How to run a script every hour, on the hour only on weekdays using time-based trigger?

I need to run a Google App Script script every hour on the hour only on weekdays.

It seems easy to do one of the two, but to combine it I'm not sure...

The hourly trigger: ScriptApp.newTrigger("RefreshRates").timeBased().inTimezone("GMT").everyHours(1).nearMinute(0).create();

It needs to run every hour as close as possible to the hour. So for example 09:00, 10:00, 11:00 etc. I know App Script not very accurate with this but then just as close as possible to the hour.

I found this that might help with the weekdays issue, but is it possible to then combine the above with something like this:

 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();
    }
 }

Ideal is actually Friday 9:45 pm till 10:15pm Sunday GMT, when Forex markets close and open...

Edit: I think I made something not very clear in my initial question about every hour every weekday, not certain hours. But the week for markets start 22:00 Sunday GMT and ends Friday 22:00 GMT. Thus the ideal is from Sunday 22:00 GMT until Friday 22:00 GMT every hour around the hour...

Upvotes: 3

Views: 5346

Answers (1)

0Valt
0Valt

Reputation: 10345

Your best choice, I think, would be setting a Trigger to each hour you want the script to run at, using a second loop inside the one that sets weekdays, since everyHours() does not accept start and end arguments.

Please, note that this will create separate triggers that fire on the same day of the week.

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);
    }        
  });

}

As an update to the answer - please, note that, unfortunately, there are quotas on how many triggers you may create for the project on behalf of one user (currently equals to 20 per user per project).

Configurable triggers

As clarified in comments, configuring custom-days + custom-hours triggers requires a more sophisticated handling. Proposed solution (not counting explicit date-time checks) is dynamic trigger configuration (since one cannot set both the onWeekDay(day) + everyHours(n) due to recurrence overlapping [I found that onWeekDay(day) sets implicit everyWeeks(1) recurrence pattern]):

First, create a main trigger function that sets days recurrence

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;
    }
  });

}

Secondly, create a trigger change function that will be fired with set recurrence, which clears previously set triggers and creates new ones:

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;
}

Upvotes: 2

Related Questions