Time trigger GAS at exact time every 15 min

Viewed 179

My goal is to create a trigger time base in Google App Script to run a function every 15 minutes starting from a specific minute, example: 11:01 - 11:16 - 11:31 - 11:46 --> so starting point 11:01 and then every 15 minutes, every day.

I know that this is not a new problem but I've searched a lot and I've found only these answers:

It's possible run Google Sheets script Exact Time Everyday?

Run a Gmail Google Apps Script daily at 8:00, 12:30, 17:00

https://github.com/davidtheweiss/Apps-Script-Season-3-Script-Service/blob/master/Episode%201.1.gs

Unfortunatelly none of them works, in particular my try was:

function setTrigger() {

deleteTriggers();  
var times = [[11,01],[11,16],[11,31],[11,46],[12,01],[12,16],[12,31],[12,46],[13,01],[13,16],
[13,31],[13,46],[14,01],[14,16],[14,31],[14,46],[15,01],[15,16],[15,31],[15,46],[16,01],[16,16],
[16,31],[16,46],[17,01],[17,16],[17,31],[17,46],[18,01],
[18,16],[18,31],[18,46],[19,01],[19,16],[19,31],[19,46],[20,01],[20,16],
[20,31],[20,46],[21,01][10,36],[10,46],[11,01],[11,16],[11,31],[11,46],[12,01]]; // 9:30 am, 9:45 am, 10:00 am 12:00pm
times.forEach(t_el => scheduledTrigger(t_el[0],t_el[1]));
}

function scheduledTrigger(hours,minutes){
  
var today_D = new Date();  
var year = today_D.getFullYear();
var month = today_D.getMonth();
var day = today_D.getDate();
  
pars = [year,month,day,hours,minutes];
  
var scheduled_D = new Date(...pars);
var hours_remain=Math.abs(scheduled_D - today_D) / 36e5;
ScriptApp.newTrigger("function_Triggered")
.timeBased()
.after(hours_remain * 60 *60 * 1000)
.create()
}

function deleteTriggers() {
  
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
  if (   triggers[i].getHandlerFunction() == "function_Triggered") {
    ScriptApp.deleteTrigger(triggers[i]);
  }
}
}

function function_Triggered() {
 // your function code here
}

But the problem is that it creates way too much triggers at the same time and it gives me error for this reason

3 Answers

If you do not care about trigger precision (+- 1 minute of desired time or so): use everyMinutes(n) trigger and inside callback function check which minute it is:

  • if not minute you need, skip execution
  • if exact minute you need - do your thing

If you DO care about precision (like it should be exact minute you need and not previous or next) in your case Apps Script is not helpful at all, you may want to use some workaround, for example:

  1. Set up some simple Node.js App Engine cron job (which will have great precision).
  2. Inside cron function call your Apps Script (deployed as Web App).

This will allow you to have your Apps Script function executed at exact time you need.

Try this : create a function that will test date, hour and minute. Then include the result in your own function on which you apply a trigger "every minute"

//put a trigger every minute
function function_Triggered(){
  if (testDateHour()==true) {
    // here is your script
  }
}
function testDateHour(){
  var d = new Date();
  // not on sunday and saturday and between 10am and 4pm each 15mn
  if (d.getDay()!=0 && d.getDay()!=6 && d.getHours()>=10 && d.getHours()<=16 && d.getMinutes()%15==1) {return true}else{return false}
}

There are 2 ways to do it (actually the same logic):

Method A: Create a every 15 minute trigger, which create a trigger of function_Triggered in (every) nearest 15 minute.

Method B: Include a trigger create function in function_Triggered, which create trigger of function_Triggered in (next) nearest 15 minute.

Reference:

timeBased().at(date)


function function_Triggered() {
  try { /* ... */ }
  catch(e) { /* ... */ }
  finally { setTrigger('function_Triggered', 15); }
}

function setTrigger(funcName, min) {
  deleteTrigger(funcName);
  let date = new Date();
  const diff = 1000 * 60 * min;
  date = new Date(Math.floor(date.getTime() / diff + 1) * diff);
  ScriptApp.newTrigger(funcName).timeBased().at(date).create();
}

function deleteTrigger(funcName) {
  const triggers = ScriptApp.getProjectTriggers();
  for (const trigger of triggers) {
    if (trigger.getHandlerFunction() === funcName) {
      ScriptApp.deleteTrigger(trigger);
    }
  }
}
Related