Advanced Calendar Service

The advanced Calendar service allows you to use the public Google Calendar API in Apps Script. Much like Apps Script's built-in Calendar service, this API allows scripts to access and modify the user's Google Calendar, including additional calendars that the user is subscribed to. In most cases, the built-in service is easier to use, but this advanced service provides a few extra features, including setting the background color for individual events.

Reference

For detailed information on this service, see the reference documentation for the public Google Calendar API. Like all advanced services in Apps Script, the advanced Calendar service uses the same objects, methods, and parameters as the public API.

To report issues and find other support, see the Calendar support guide.

HTTP request headers

The advanced Calendar service can accept the HTTP request headers If-Match and If-None-Match. For details, see the reference documentation.

Sample code

The sample code below uses version 3 of the API.

Creating events

The following example demonstrates how to create an event in the user's default calendar.

advanced/calendar.gs
/**
 * Creates an event in the user's default calendar.
 */
function createEvent() {
  var calendarId = 'primary';
  var start = getRelativeDate(1, 12);
  var end = getRelativeDate(1, 13);
  var event = {
    summary: 'Lunch Meeting',
    location: 'The Deli',
    description: 'To discuss our plans for the presentation next week.',
    start: {
      dateTime: start.toISOString(),
    },
    end: {
      dateTime: end.toISOString(),
    },
    attendees: [
      {email: 'alice@example.com'},
      {email: 'bob@example.com'},
    ],
    // Red background. Use Calendar.Colors.get() for the full list.
    colorId: 11,
  };
  event = Calendar.Events.insert(event, calendarId);
  Logger.log('Event ID: ' + event.getId());
}

/**
 * Helper function to get a new Date object relative to the current date.
 * @param {number} daysOffset The number of days in the future for the new date.
 * @param {number} hour The hour of the day for the new date, in the time zone
 *     of the script.
 * @return {Date} The new date.
 */
function getRelativeDate(daysOffset, hour) {
  var date = new Date();
  date.setDate(date.getDate() + daysOffset);
  date.setHours(hour);
  date.setMinutes(0);
  date.setSeconds(0);
  date.setMilliseconds(0);
  return date;
}

Listing calendars

The following example demonstrates how to retrieve details about the calendars shown in the user's calendar list.

advanced/calendar.gs
/**
 * Lists the calendars shown in the user's calendar list.
 */
function listCalendars() {
  var calendars;
  var pageToken;
  do {
    calendars = Calendar.CalendarList.list({
      maxResults: 100,
      pageToken: pageToken,
    });
    if (calendars.items && calendars.items.length > 0) {
      for (var i = 0; i < calendars.items.length; i++) {
        var calendar = calendars.items[i];
        Logger.log('%s (ID: %s)', calendar.summary, calendar.id);
      }
    } else {
      Logger.log('No calendars found.');
    }
    pageToken = calendars.nextPageToken;
  } while (pageToken);
}

Listing events

The following example demonstrates how to list the next 10 upcoming events in the user's default calendar.

advanced/calendar.gs
/**
 * Lists the next 10 upcoming events in the user's default calendar.
 */
function listNext10Events() {
  var calendarId = 'primary';
  var now = new Date();
  var events = Calendar.Events.list(calendarId, {
    timeMin: now.toISOString(),
    singleEvents: true,
    orderBy: 'startTime',
    maxResults: 10,
  });
  if (events.items && events.items.length > 0) {
    for (var i = 0; i < events.items.length; i++) {
      var event = events.items[i];
      if (event.start.date) {
        // All-day event.
        var start = new Date(event.start.date);
        Logger.log('%s (%s)', event.summary, start.toLocaleDateString());
      } else {
        var start = new Date(event.start.dateTime);
        Logger.log('%s (%s)', event.summary, start.toLocaleString());
      }
    }
  } else {
    Logger.log('No events found.');
  }
}

Conditionally modifying an event

The following example shows how to conditionally update a Calendar event using the If-Match header. The script creates a new event, waits 30 seconds, then updates the event only if no event details have changed since the event was created.

advanced/calendar.gs
/**
 * Creates an event in the user's default calendar, waits 30 seconds, then
 * attempts to update the event's location, on the condition that the event
 * has not been changed since it was created.  If the event is changed during
 * the 30-second wait, then the subsequent update will throw a 'Precondition
 * Failed' error.
 *
 * The conditional update is accomplished by setting the 'If-Match' header
 * to the etag of the new event when it was created.
 */
function conditionalUpdate() {
  var calendarId = 'primary';
  var start = getRelativeDate(1, 12);
  var end = getRelativeDate(1, 13);
  var event = {
    summary: 'Lunch Meeting',
    location: 'The Deli',
    description: 'To discuss our plans for the presentation next week.',
    start: {
      dateTime: start.toISOString(),
    },
    end: {
      dateTime: end.toISOString(),
    },
    attendees: [
      {email: 'alice@example.com'},
      {email: 'bob@example.com'},
    ],
    // Red background. Use Calendar.Colors.get() for the full list.
    colorId: 11,
  };
  event = Calendar.Events.insert(event, calendarId);
  Logger.log('Event ID: ' + event.getId());
  // Wait 30 seconds to see if the event has been updated outside this script.
  Utilities.sleep(30 * 1000);
  // Try to update the event, on the condition that the event state has not
  // changed since the event was created.
  event.location = 'The Coffee Shop';
  try {
    event = Calendar.Events.update(
      event,
      calendarId,
      event.id,
      {},
      {'If-Match': event.etag}
    );
    Logger.log('Successfully updated event: ' + event.id);
  } catch (e) {
    Logger.log('Fetch threw an exception: ' + e);
  }
}

Conditionally retrieving an event

The following example shows how to conditionally fetch a Calendar event using the If-None-Match header. The script creates a new event, then polls the event for changes for 30 seconds. Any time the event changes, the new version is fetched.

advanced/calendar.gs
/**
 * Creates an event in the user's default calendar, then re-fetches the event
 * every second, on the condition that the event has changed since the last
 * fetch.
 *
 * The conditional fetch is accomplished by setting the 'If-None-Match' header
 * to the etag of the last known state of the event.
 */
function conditionalFetch() {
  var calendarId = 'primary';
  var start = getRelativeDate(1, 12);
  var end = getRelativeDate(1, 13);
  var event = {
    summary: 'Lunch Meeting',
    location: 'The Deli',
    description: 'To discuss our plans for the presentation next week.',
    start: {
      dateTime: start.toISOString(),
    },
    end: {
      dateTime: end.toISOString(),
    },
    attendees: [
      {email: 'alice@example.com'},
      {email: 'bob@example.com'},
    ],
    // Red background. Use Calendar.Colors.get() for the full list.
    colorId: 11,
  };
  event = Calendar.Events.insert(event, calendarId);
  Logger.log('Event ID: ' + event.getId());
  // Re-fetch the event each second, but only get a result if it has changed.
  for (var i = 0; i < 30; i++) {
    Utilities.sleep(1000);
    try {
      event = Calendar.Events.get(calendarId, event.id, {}, {'If-None-Match': event.etag});
      Logger.log('New event description: ' + event.description);
    } catch (e) {
      Logger.log('Fetch threw an exception: ' + e);
    }
  }
}

Synchronizing events

The following example demonstrates how to retrieve events using sync tokens. When you include a sync token in a Calendar advanced service request, the resulting response only includes items that have changed since that token was generated, enabling more efficient processing. See Synchronize Resources Efficiently for more details on the syncing process.

The following example makes use of the same getRelativeDate(daysOffset, hour) method defined in the above examples.

advanced/calendar.gs
/**
 * Retrieve and log events from the given calendar that have been modified
 * since the last sync. If the sync token is missing or invalid, log all
 * events from up to a month ago (a full sync).
 *
 * @param {string} calendarId The ID of the calender to retrieve events from.
 * @param {boolean} fullSync If true, throw out any existing sync token and
 *        perform a full sync; if false, use the existing sync token if possible.
 */
function logSyncedEvents(calendarId, fullSync) {
  var properties = PropertiesService.getUserProperties();
  var options = {
    maxResults: 100,
  };
  var syncToken = properties.getProperty('syncToken');
  if (syncToken && !fullSync) {
    options.syncToken = syncToken;
  } else {
    // Sync events up to thirty days in the past.
    options.timeMin = getRelativeDate(-30, 0).toISOString();
  }

  // Retrieve events one page at a time.
  var events;
  var pageToken;
  do {
    try {
      options.pageToken = pageToken;
      events = Calendar.Events.list(calendarId, options);
    } catch (e) {
      // Check to see if the sync token was invalidated by the server;
      // if so, perform a full sync instead.
      if (e.message === 'Sync token is no longer valid, a full sync is required.') {
        properties.deleteProperty('syncToken');
        logSyncedEvents(calendarId, true);
        return;
      } else {
        throw new Error(e.message);
      }
    }

    if (events.items && events.items.length > 0) {
      for (var i = 0; i < events.items.length; i++) {
         var event = events.items[i];
         if (event.status === 'cancelled') {
           console.log('Event id %s was cancelled.', event.id);
         } else if (event.start.date) {
           // All-day event.
           var start = new Date(event.start.date);
           console.log('%s (%s)', event.summary, start.toLocaleDateString());
         } else {
           // Events that don't last all day; they have defined start times.
           var start = new Date(event.start.dateTime);
           console.log('%s (%s)', event.summary, start.toLocaleString());
         }
      }
    } else {
      console.log('No events found.');
    }

    pageToken = events.nextPageToken;
  } while (pageToken);

  properties.setProperty('syncToken', events.nextSyncToken);
}

Enviar comentários sobre…

Precisa de ajuda? Acesse nossa página de suporte.