管理专注时间、不在办公室和工作地点活动

本页面介绍了如何使用 Google Calendar API 创建显示 Google 日历用户状态的活动。状态事件描述了用户所在的位置或正在进行的活动,包括他们是处于专注时间、不在办公室,还是在特定地点工作。

在 Google 日历中,用户可以创建专注时间、不在办公室和工作地点活动,以指示其自定义状态和地点。这些功能仅适用于主日历,且仅适用于部分 Google 日历用户。

有关详情,请参阅在 Google 日历中使用专注时间为用户启用或停用工作地点

读取和列出 Google 日历状态活动

您可以在日历 API 的 Events 资源中读取和列出日历状态事件。

如需读取某个状态事件,请使用 events.get 方法,并指定事件的 eventId

如需列出状态事件,请使用 events.list 方法,并在 eventTypes 字段中指定以下一个或多个值:

  • 'focusTime'
  • 'outOfOffice'
  • 'workingLocation'

然后,在返回的 Event 对象中,检查 eventType 字段是否包含请求的值,并参考相应字段以详细了解用户在 Google 日历中创建的状态:

订阅状态更改事件

您可以在日历 API 的 Events 资源中订阅状态事件更改。

使用 events.watch 方法,指定要订阅的日历的 calendarId,并在 eventTypes 字段中指定以下一个或多个值:

  • 'focusTime'
  • 'outOfOffice'
  • 'workingLocation'

创建和更新 Google 日历状态活动

如需创建状态事件,您可以使用 events.insert 方法创建 Events 资源实例,并为事件类型设置必填字段。

如果您使用 events.update 方法更新状态事件,该事件必须保留必填字段。

创建专注时间

要创建专注时间活动,请执行以下操作:

  • eventType 设置为 'focusTime'
  • 添加 focusTimeProperties 字段。
  • transparency 字段设置为 'opaque'
  • 将事件的 startend 字段设置为定时事件(已指定开始时间和结束时间)。
    专注时间不能是全天活动。

如需详细了解功能,请参阅在 Google 日历中使用专注时间

创建“不在办公室”设置

要创建“不在办公室”活动,请执行以下操作:

  • eventType 设置为 'outOfOffice'
  • 添加 outOfOfficeProperties 字段。
  • transparency 字段设置为 'opaque'
  • 将事件的 startend 字段设置为定时事件(已指定开始时间和结束时间)。
    “不在办公室”活动不能是全天活动。

如需详细了解功能,请参阅显示您的“不在办公室”状态

创建工作地点

如需创建工作地点活动,请执行以下操作:

  • eventType 设置为 'workingLocation'
  • 添加 workingLocationProperties 字段。
  • visibility 字段设置为 'public'
  • transparency 字段设置为 'transparent'
  • 将事件的 startend 字段设置为以下任一项:

    • 计时事件(已指定开始时间和结束时间);
    • 只持续一天的全天事件(已指定开始日期和结束日期)。

    全天工作地点事件不能跨越多个日期,但计时事件可以跨越多个日期。

以下字段是可选的,但建议填写,以便在插入 officeLocation 时提供最佳用户体验:

不支持通过批处理端点创建和更新工作地点事件。

如需详细了解功能,请参阅设置您的工作时间和地点为用户启用或停用工作地点

如何显示工作地点重叠的事件

用户的日历上可以同时有多个重叠的工作地点活动,这意味着可以在任何给定时间为其设置多个工作地点。如果只能向用户显示一个位置信息,应在多个应用中一致地向用户显示该位置信息。执行此操作时,请遵循以下准则来选择要显示的事件:

  • 定时事件优先于全天事件。
  • 单个活动优先于周期性活动及其例外情况
  • 较晚开始的事件优先于较早开始的事件。
  • 持续时间较短的事件优先于持续时间较长的事件。
  • 最近创建的事件优先于之前创建的事件。
  • 部分重叠的事件应显示为两个不同的事件,每个事件都有自己的工作地点。

在 Google Apps 脚本中创建状态事件

Google Apps 脚本是一种基于 JavaScript 的云脚本语言,可让您构建与 Google Workspace 集成的业务应用。脚本是在基于浏览器的代码编辑器中开发的,它们在 Google 的服务器上存储和运行。另请参阅 Google Apps 脚本快速入门,了解如何开始使用 Apps 脚本向 Google Calendar API 发送请求。

以下说明介绍了如何使用 Google 日历 API 作为 Google Apps 脚本中的高级服务来管理状态事件。如需查看 Google 日历 API 资源和方法的完整列表,请参阅参考文档

创建和设置脚本

  1. 前往 script.google.com/create 创建脚本。
  2. 在左侧窗格中,点击服务旁边的“添加服务”图标
  3. 选择 Google Calendar API,然后点击添加
  4. 启用后,该 API 将在左侧窗格中显示。您可以在编辑器中使用日历关键字列出 API 中的可用方法和类。

(可选)更新 Google Cloud 项目

每个 Google Apps 脚本项目都有一个关联的 Google Cloud 项目。您的脚本可以使用 Google Apps 脚本自动创建的默认项目。如果您想要使用自定义 Google Cloud 项目,请按照以下步骤更新与您的脚本关联的项目。

  1. 在编辑器的左侧,点击“Project Settings”图标
  2. Google Cloud Platform (GCP) 项目下,点击更改项目
  3. 输入开发者预览版计划的 Google Cloud 项目的项目编号,然后点击设置项目
  4. 在左侧,选择“Editor” 以返回到代码编辑器。

向脚本添加代码

以下代码示例展示了如何在主日历上创建、读取和列出状态事件。

  1. 将以下内容粘贴到代码编辑器中。

    /** Creates a focus time event. */
    function createFocusTime() {
      const event = {
        start: { dateTime: '2023-11-14T10:00:00+01:00' },
        end: { dateTime: '2023-11-14T12:00:00+01:00' },
        eventType: 'focusTime',
        focusTimeProperties: {
          chatStatus: 'doNotDisturb',
          autoDeclineMode: 'declineOnlyNewConflictingInvitations',
          declineMessage: 'Declined because I am in focus time.',
        }
      }
      createEvent(event);
    }
    
    /** Creates an out of office event. */
    function createOutOfOffice() {
      const event = {
        start: { dateTime: '2023-11-15T10:00:00+01:00' },
        end: { dateTime: '2023-11-15T18:00:00+01:00' },
        eventType: 'outOfOffice',
        outOfOfficeProperties: {
          autoDeclineMode: 'declineOnlyNewConflictingInvitations',
          declineMessage: 'Declined because I am on vacation.',
        }
      }
      createEvent(event);
    }
    
    /** Creates a working location event. */
    function createWorkingLocation() {
      const event = {
        start: { date: "2023-06-01" },
        end: { date: "2023-06-02" },
        eventType: "workingLocation",
        visibility: "public",
        transparency: "transparent",
        workingLocationProperties: {
          type: 'customLocation',
          customLocation: { label: "a custom location" },
        }
      }
      createEvent(event);
    }
    
    /**
      * Creates a Calendar event.
      * See https://developers.google.com/calendar/api/v3/reference/events/insert
      */
    function createEvent(event) {
      const calendarId = 'primary';
    
      try {
        var response = Calendar.Events.insert(event, calendarId);
        var event = (response.eventType === 'workingLocation') ? parseWorkingLocation(response) : response;
        console.log(event);
      } catch (exception) {
        console.log(exception.message);
      }
    }
    
    /**
      * Reads the event with the given eventId.
      * See https://developers.google.com/calendar/api/v3/reference/events/get
      */
    function readEvent() {
      const calendarId = 'primary';
    
      // Replace with a valid eventId.
      const eventId = "sample-event-id";
    
      try {
        var response = Calendar.Events.get(calendarId, eventId);
        var event = (response.eventType === 'workingLocation') ? parseWorkingLocation(response) : response;
        console.log(event);
      } catch (exception) {
        console.log(exception.message);
      }
    }
    
    /** Lists focus time events. */
    function listFocusTimes() {
      listEvents('focusTime');
    }
    
    /** Lists out of office events. */
    function listOutOfOffices() {
      listEvents('outOfOffice');
    }
    
    /** Lists working location events. */
    function listWorkingLocations() {
      listEvents('workingLocation');
    }
    
    /**
      * Lists events with the given event type.
      * See https://developers.google.com/calendar/api/v3/reference/events/list
      */
    function listEvents(eventType = 'default') {
      const calendarId = 'primary'
    
      // Query parameters for the list request.
      const optionalArgs = {
        eventTypes: [eventType],
        showDeleted: false,
        singleEvents: true,
        timeMax: '2023-04-01T00:00:00+01:00',
        timeMin: '2023-03-27T00:00:00+01:00',
      }
      try {
        var response = Calendar.Events.list(calendarId, optionalArgs);
        response.items.forEach(event =>
          console.log(eventType === 'workingLocation' ? parseWorkingLocation(event) : event));
      } catch (exception) {
        console.log(exception.message);
      }
    }
    
    /**
      * Parses working location properties of an event into a string.
      * See https://developers.google.com/calendar/api/v3/reference/events#resource
      */
    function parseWorkingLocation(event) {
      if (event.eventType != "workingLocation") {
        throw new Error("'" + event.summary + "' is not a working location event.");
      }
    
      var location = 'No Location';
      const workingLocation = event.workingLocationProperties;
      if (workingLocation) {
        if (workingLocation.type === 'homeOffice') {
          location = 'Home';
        }
        if (workingLocation.type === 'officeLocation') {
          location = workingLocation.officeLocation.label;
        }
        if (workingLocation.type === 'customLocation') {
          location = workingLocation.customLocation.label;
        }
      }
      return `${event.start.date}: ${location}`;
    }
    

运行代码示例

  1. 在代码编辑器上方,从下拉菜单中选择要运行的函数,然后点击运行
  2. 在第一次执行时,它会提示您授予访问权限。查看并允许 Apps 脚本访问您的日历。
  3. 您可以在窗口底部显示的执行日志中检查脚本的执行结果。