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