var SOURCE_CALENDAR_ID = 'nrasmussen@gainsight.com'; // OR the full calendar id including @something.calendar.google.com var SCRUBBED_CALENDAR_ID = 'c_9ad3baa9ffa4f385829b7618918d123d3b2c39a111a45d1d645b0e29d8fda68b@group.calendar.google.com'; var WEEKS_IN_ADVANCE = 1; // The maximum script run time under Apps Script Pro is 30 minutes; this setting // will be used to report when the script is about to reach that limit. var MAX_PRO_RUNTIME_MS = 29 * 60 * 1000; /** * Look through the source calendar and copy all non-all-day events to the scrubbed calendar */ function syncCalendarAfterScrubbing() { // Define the calendar event date range to search. var today = new Date(); var futureDate = new Date(); futureDate.setDate(futureDate.getDate() + WEEKS_IN_ADVANCE*7); var lastRun = PropertiesService.getScriptProperties().getProperty('lastRun'); lastRun = lastRun ? new Date(lastRun) : null; if (isTimeUp(today, new Date())) { Logger.log('Execution time about to hit quota limit; execution stopped.'); return; } // find events that are not all-day in the specified date range. // Import each of those to the scrubbed calendar. var count = 0; var events = findEvents(SOURCE_CALENDAR_ID, today, futureDate, lastRun); Logger.log(events); events.forEach(function(event) { event.organizer = { id: SCRUBBED_CALENDAR_ID } event.attendees = []; Logger.log('Importing: %s', event.summary); try { Calendar.Events.import(event, SCRUBBED_CALENDAR_ID); count++; } catch (e) { Logger.log( 'Error attempting to import event: %s. Skipping.', e.toString()); } }); PropertiesService.getScriptProperties().setProperty('lastRun', today); Logger.log('Imported ' + count + ' events'); var executionTime = ((new Date()).getTime() - today.getTime()) / 1000.0; Logger.log('Total execution time (s) : ' + executionTime); ; } /** * In a given calendar, look for non-all-day events * in events within the specified date range and return any such events * found. * @param {string} cal_id the ID of the source calendar * @param {Date} start the starting Date of the range to examine. * @param {Date} end the ending Date of the range to examine. * @param {Date} opt_since a Date indicating the last time this script was run. * @return {object[]} an array of calendar event Objects. */ function findEvents(cal_id, start, end, opt_since) { var params = { timeMin: formatDate(start), timeMax: formatDate(end), showDeleted: true }; if (opt_since) { // This prevents the script from examining events that have not been // modified since the specified date (that is, the last time the // script was run). params['updatedMin'] = formatDate(opt_since); } var results = []; try { var response = Calendar.Events.list(cal_id, params); results = response.items.filter(function(item) { // Filter out events where the owner of the script has not accepted if (item.attendees) { for (person of item.attendees) { if (person['self'] == true && person['responseStatus'] != "accepted") { return false; } } } // Filter out events where the event is all-day if (item.start.date) { return false; } return true; }); } catch (e) { Logger.log('Error retriving events for %s; skipping', e.toString()); results = []; } return results; } /** * Return an RFC3339 formated date String corresponding to the given * Date object. * @param {Date} date a Date. * @return {string} a formatted date string. */ function formatDate(date) { return Utilities.formatDate(date, 'UTC', 'yyyy-MM-dd\'T\'HH:mm:ssZ'); } /** * Compares two Date objects and returns true if the difference * between them is more than the maximum specified run time. * * @param {Date} start the first Date object. * @param {Date} now the (later) Date object. * @return {boolean} true if the time difference is greater than * MAX_PROP_RUNTIME_MS (in milliseconds). */ function isTimeUp(start, now) { return now.getTime() - start.getTime() > MAX_PRO_RUNTIME_MS; }