重复周期模式和 EWS

了解 Exchange 中的重复周期模式和定期系列。

定期系列是根据定义的模式重复的约会或会议。 定期序列可以有特定数量的出现,也可以无限期重复。 此外,定期序列可能具有不符合其余事件模式的异常,并且可能具有已从模式中删除的异常。 可以使用 EWS 托管 API 和 EWS 来处理定期系列及其关联的日历项。

定期日历项

所有日历项分为以下四个类别之一:

  • 非定期日历项

  • 定期主控服务器

  • 序列中的出现次数

  • 序列中修改的匹配项,称为异常

在本文中,我们将介绍属于定期系列的三种类型的日历项。

了解如何在 Exchange 服务器上实现定期系列会很有帮助。 服务器在日历中只创建一个实际项目(称为定期主控形状),而不是为定期系列中的每个事件创建单独的不同项。 定期主数据库的格式与非定期约会非常相似,并添加了重复模式信息。 然后,服务器使用称为扩展的过程,根据重复模式生成事件,以响应客户端对约会信息的请求。 这些生成的事件不会永久存储在服务器上。 了解这一点很重要,因为搜索日历项的方式决定了你收到的信息以及是否发生扩展。

定期模式

使扩展成为可能的定期序列的关键部分是重复模式。 定期模式在定期主数据库上找到,并描述了一组基于定期主节点的日期和时间计算出现次数的条件。

表 1. 可用定期模式

EWS 托管 API 类 EWS 元素 示例
Recurrence.DailyPattern
DailyRecurrence
每天重复一次。
每隔一天重复一次。
Recurrence.MonthlyPattern
AbsoluteMonthlyRecurrence
每月第十天重复一次。
在每月的第二十一天每隔一个月重复一次。
Recurrence.RelativeMonthlyPattern
RelativeMonthlyRecurrence
在每个月的第二个星期二重复。
每三个月在每月的第三个星期四重复一次。
Recurrence.RelativeYearlyPattern
RelativeYearlyRecurrence
在每年 8 月的第一个星期一重复。
Recurrence.WeeklyPattern
WeeklyRecurrence
每周一重复一次。
每星期二和星期四重复一次。
Recurrence.YearlyPattern
AbsoluteYearlyRecurrence
每年 9 月 1 日重复。

定期模式的另一个重要信息是定期结束时间。 这可以表示为一定数量的出现次数、结束日期或没有结束。

表 2. 定期系列末尾的选项

EWS 托管 API 方法/属性 EWS 元素 说明
Recurrence.NumberOfOccurrences
NumberedRecurrence
此属性或元素的值指定出现次数。
Recurrence.EndDate
EndDateRecurrence
序列中的最后一个匹配项位于此属性或元素指定的日期或之前。
Recurrence.HasEnd
Recurrence.NeverEnds
NoEndRecurrence
该系列没有终点。

展开视图与非扩展视图

在 EWS 托管 API (中使用 FindAppointments 方法或使用 EWS 中的 CalendarView 元素的 FindItem 操作) 调用扩展过程。 这会从结果集中隐藏定期主约会,而是显示该定期系列的扩展视图。 结果集中包含属于日历视图参数的定期主控形状的 和 异常。 相反,在 EWS 托管 API (中使用 FindItems 方法或在 EWS) 中使用 IndexedPageItemViewFractionalPageItemView 元素的 FindItem 操作,不会调用扩展过程,并且不包括出现和异常。 让我们看一个比较这两种方法的示例。

表 3. 用于查找约会的方法和操作

EWS 托管的 API 方法 EWS 操作 扩展系列? 结果中包含的项
ExchangeService.FindAppointments
使用 CalendarView 元素执行 FindItem 操作

非定期约会、定期系列单次出现以及定期系列异常
ExchangeService.FindItems
使用 IndexedPageItemView 元素或 FractionalPageItemView 元素的 FindItem操作

非定期约会和定期主约会

萨迪刚刚签下她的儿子去游泳队。 球队从7月2日开始,每周三上午8:30练习,最后一次练习是在8月6日。 不想忘记练习,萨迪在日历上增加了一个定期约会来提醒她。

表 4. 萨迪的定期约会

“约会”域
主题
游泳队练习
开始
2014 年 7 月 2 日上午 8:30
End
2014 年 7 月 2 日上午 10:00
复发
每周三
上次出现次数
2014 年 8 月 6 日上午 8:30

快速查看日历后,团队将总共有六个做法。 但是,日历中没有六个不同的约会项。 相反,只有一个代表序列的定期主约会。

现在,让我们看看在萨迪的日历上查找在 7 月内发生的约会。 下面的代码示例使用 Exchange 托管 API 中的 FindItems 方法生成 Sadie 日历的非扩展视图。

PropertySet propSet = new PropertySet(AppointmentSchema.Subject,
                                      AppointmentSchema.Location,
                                      AppointmentSchema.Start, 
                                      AppointmentSchema.End,
                                      AppointmentSchema.AppointmentType);
#region FindItems + ItemView method
ItemView itemView = new ItemView(100);
itemView.PropertySet = propSet;
List<SearchFilter> filterList = new List<SearchFilter>();
// Find appointments that start after midnight on July 1, 2014.
SearchFilter.IsGreaterThan startFilter = new SearchFilter.IsGreaterThan(AppointmentSchema.Start,
    new DateTime(2014, 7, 1));
// Find appointments that end before midnight on July 31, 2014
SearchFilter.IsLessThan endFilter = new SearchFilter.IsLessThan(AppointmentSchema.End,
    new DateTime(2014, 7, 31));
filterList.Add(startFilter);
filterList.Add(endFilter);
SearchFilter.SearchFilterCollection calendarFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, filterList);
// This results in a call to EWS.
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Calendar, calendarFilter, itemView);
foreach(Item appt in results.Items)
{
    Console.WriteLine(appt.Subject);
}

该代码将生成以下具有 IndexedPageItemView 元素的 FindItem操作请求。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
    xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" 
    xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
    <t:TimeZoneContext>
      <t:TimeZoneDefinition Id="Pacific Standard Time" />
    </t:TimeZoneContext>
  </soap:Header>
  <soap:Body>
    <m:FindItem Traversal="Shallow">
      <m:ItemShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="item:Subject" />
          <t:FieldURI FieldURI="calendar:Location" />
          <t:FieldURI FieldURI="calendar:Start" />
          <t:FieldURI FieldURI="calendar:End" />
          <t:FieldURI FieldURI="calendar:CalendarItemType" />
        </t:AdditionalProperties>
      </m:ItemShape>
      <m:IndexedPageItemView MaxEntriesReturned="100" Offset="0" BasePoint="Beginning" />
      <m:Restriction>
        <t:And>
          <t:IsGreaterThan>
            <t:FieldURI FieldURI="calendar:Start" />
            <t:FieldURIOrConstant>
              <t:Constant Value="2014-07-01T07:00:00.000Z" />
            </t:FieldURIOrConstant>
          </t:IsGreaterThan>
          <t:IsLessThan>
            <t:FieldURI FieldURI="calendar:End" />
            <t:FieldURIOrConstant>
              <t:Constant Value="2014-07-31T07:00:00.000Z" />
            </t:FieldURIOrConstant>
          </t:IsLessThan>
        </t:And>
      </m:Restriction>
      <m:ParentFolderIds>
        <t:DistinguishedFolderId Id="calendar" />
      </m:ParentFolderIds>
    </m:FindItem>
  </soap:Body>
</soap:Envelope>

服务器的响应仅包括单个项,即定期主控形状,由 RecurrenceingMasterCalendarItemType 元素值指示。 为了便于阅读,已缩短 ItemId 元素的值。

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="939" MinorBuildNumber="16" Version="V2_11" 
        xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns="https://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:FindItemResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
        xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:FindItemResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:RootFolder IndexedPagingOffset="1" TotalItemsInView="1" IncludesLastItemInRange="true">
            <t:Items>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA5..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-02T15:30:00Z</t:Start>
                <t:End>2014-07-02T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>RecurringMaster</t:CalendarItemType>
              </t:CalendarItem>
            </t:Items>
          </m:RootFolder>
        </m:FindItemResponseMessage>
      </m:ResponseMessages>
    </m:FindItemResponse>
  </s:Body>
</s:Envelope>

现在,让我们与展开的视图进行比较。 下面的代码示例使用 EWS 托管 API 中的 FindAppointments 方法创建 Sadie 日历的扩展视图。

PropertySet propSet = new PropertySet(AppointmentSchema.Subject,
                                      AppointmentSchema.Location,
                                      AppointmentSchema.Start, 
                                      AppointmentSchema.End,
                                      AppointmentSchema.AppointmentType);
CalendarView calView = new CalendarView(new DateTime(2014, 7, 1),
    new DateTime(2014, 7, 31));
calView.PropertySet = propSet;
FindItemsResults<Appointment> results = service.FindAppointments(WellKnownFolderName.Calendar, calView);
foreach(Appointment appt in results.Items)
{
    Console.WriteLine(appt.Subject);
}

此代码使用 CalendarView 元素生成以下 FindItem 操作请求。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
    xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" 
    xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
    <t:TimeZoneContext>
      <t:TimeZoneDefinition Id="Pacific Standard Time" />
    </t:TimeZoneContext>
  </soap:Header>
  <soap:Body>
    <m:FindItem Traversal="Shallow">
      <m:ItemShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="item:Subject" />
          <t:FieldURI FieldURI="calendar:Location" />
          <t:FieldURI FieldURI="calendar:Start" />
          <t:FieldURI FieldURI="calendar:End" />
          <t:FieldURI FieldURI="calendar:CalendarItemType" />
        </t:AdditionalProperties>
      </m:ItemShape>
      <m:CalendarView StartDate="2014-07-01T07:00:00.000Z" EndDate="2014-07-31T07:00:00.000Z" />
      <m:ParentFolderIds>
        <t:DistinguishedFolderId Id="calendar" />
      </m:ParentFolderIds>
    </m:FindItem>
  </soap:Body>
</soap:Envelope>

这一次,服务器响应包括五个事件,7 月的每个星期三一次。 这些项目上的 CalendarItemType 元素都具有 Occurrence 值。 请注意,响应中不存在定期主控服务器。 为了提高可读性, 已缩短 ItemId 元素的值。

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="939" MinorBuildNumber="16" Version="V2_11" 
        xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns="https://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:FindItemResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
        xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:FindItemResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:RootFolder TotalItemsInView="5" IncludesLastItemInRange="true">
            <t:Items>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA6..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-02T15:30:00Z</t:Start>
                <t:End>2014-07-02T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA7..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-09T15:30:00Z</t:Start>
                <t:End>2014-07-09T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA8..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-16T15:30:00Z</t:Start>
                <t:End>2014-07-16T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA9..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-23T15:30:00Z</t:Start>
                <t:End>2014-07-23T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADAA..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-30T15:30:00Z</t:Start>
                <t:End>2014-07-30T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
            </t:Items>
          </m:RootFolder>
        </m:FindItemResponseMessage>
      </m:ResponseMessages>
    </m:FindItemResponse>
  </s:Body>
</s:Envelope>

拥有定期主控形状、事件或异常后,始终可以 检索其他相关项。 给定事件或异常,可以检索定期主控服务器,反之亦然。

使用定期日历项

使用与处理非定期日历项相同的方法和操作来处理定期系列。 区别在于,根据用于调用这些方法或操作的项,所执行的操作可以应用于整个系列,也可以应用于单个事件。 对定期主数据库执行的操作 将应用于系列中的所有事件,而 对单个事件或异常执行的操作 将仅适用于该事件或异常。

本节内容

另请参阅