Auto-Decline Events Outside of Working Hours in Google Calendar

The Problem

In this age of remote work, navigating multiple timezones can sometimes result in an accidental 6am or 7pm meeting. While Google offers a “working hours” feature as part of their business plan, it can easily be missed by meeting organizers, especially if they are using a Google Calendar alternative to schedule events.

The Solution

To help mitigate this, I created a script that automatically responds to these non-working hour meetings. You can either decline the meeting, or mark your attendance as “Maybe” for a slightly less aggressive approach.

Setup Instructions

  • Create a new Google App Script project – here.
  • Copy and paste the code below into your new project.
  • Change the variables in the “User Inputs” section.
  • Run the “createMeetingResponerTrigger” to create a recurring trigger.
  • If you ever want to delete the trigger, you can run the “deleteMeetingResponerTrigger

The Code

// ----------- USER INPUTS ----------------//
var myEmail = '[email protected]';

// Days of the week you want to decline events for
// 0 for Sunday, 1 for Monday, 2 for Tuesday, and so on.
var declineDays = [6,0];

// Your working hours
var startTime = 7.5; // 7:30am
var endTime = 17; // 5:30pm

// Event Autoresponse [MAYBE, NO, YES]
var autoResponse = CalendarApp.GuestStatus.MAYBE
// -------- END OF YOUR INPUTS -------------//


function autoMeetingResponer() {
  var calendar = CalendarApp.getCalendarById(myEmail);
  var startDate = new Date();
  var endDate = new Date();
  endDate.setDate(endDate.getDate() + 14);
  
  // Get all events between the start and end dates
  var events = calendar.getEvents(startDate, endDate);
  
  for (var i = 0; i < events.length; i++) {
    // Get the event time in hours
    var eventStart = events[i].getStartTime().getHours() + (events[i].getStartTime().getMinutes() / 60);
    var eventEnd = events[i].getEndTime().getHours() + (events[i].getEndTime().getMinutes() / 60);
    var eventStatus = events[i].getMyStatus(); // Get the status of the event for the current user
    var eventDay = events[i].getStartTime().getDay(); // get the day of the week for the event
    
    // Check if the event is outside working hours OR if you are the creator of the event
    if (eventStart < startTime || eventEnd > endTime) {
            if(eventStatus == CalendarApp.GuestStatus.INVITED) {
            events[i].setMyStatus(autoResponse)
            Logger.log("Set due to time")
      }
    }

    // Check if the event is on a non-working day OR if you are the creator of the event
    if(declineDays.indexOf(eventDay) != -1){   
      if(eventStatus == CalendarApp.GuestStatus.INVITED) {
        events[i].setMyStatus(autoResponse)
        Logger.log("Set due to day")
      }
    }
  }
}


function createMeetingResponerTrigger() {
  // Create a trigger to run the autoMeetingResponer() function when a new event is added to the calendar
  ScriptApp.newTrigger('autoMeetingResponer').forUserCalendar(myEmail).onEventUpdated().create();
}

function deleteMeetingResponerTrigger() {
  // Get all existing triggers
  var triggers = ScriptApp.getProjectTriggers();
  
  // Iterate through the triggers
  for (var i = 0; i < triggers.length; i++) {
    // Check if the trigger is for the autoMeetingResponer() function
    if (triggers[i].getHandlerFunction() == "autoMeetingResponer") {
      // Delete the trigger
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}