使用 API 编辑工作时间日历

组织通常需要以编程方式创建、编辑或删除资源日历上的工作时间。 日历显示工作时间、休息时间和工间休息时间,这些在计划工作时确定资源的可用性。 资源必须在特定时区内计划,可能会也可能不会考虑节假日时间,而且可能有可变产能。 有关在 Field Service 应用中定义工作时间的信息,请转到向可预订资源添加工作时间

除了使用 Field Service 应用之外,您还可以使用以下 API 修改所选记录类型的日历规则:

  • 保存日历 API (msdyn_SaveCalendar) 根据作为请求传递的输入在选定实体上创建或更新日历记录。
  • 删除日历 API (msdyn_DeleteCalendar) 根据作为请求传递的输入删除所选实体上日历的所有内部日历规则
  • 保存/删除日历 API V2(msdyn_SaveCalendar/msdyn_DeleteCalendar,传递标志 UseV2)通过更改重叠的规则的逻辑来允许多个工作时间同时重复发生。 有关详细信息,请参阅如果存在重叠的规则,会发生什么情况?

本文包含有关每个 API 的输入(请求)和输出(响应)及其使用的详细信息,并提供了示例。

先决条件

  • 平台版本 9.2.21055 或更高版本,装有 Universal Resource Scheduling 版本 3.12.45.7。
  • 使用以下记录类型之一:
    • 可预订资源 (bookableresource)
    • 资源要求 (msdyn_resourcerequirement)
    • 工作时间模板 (msdyn_workhourtemplate)
    • 项目 (msdyn_project)

日历事件类型

创建日历时,您可以定义工作时间类型将发生多少次(一次、全天、每周或每天),或者您可以创建自定义定期发生。 有关这些日历事件的详细信息,请转到本文后面的示例

出现次数

当一个工作时间类型在实体的日历中只发生一次时,它被称为发生

例如,考虑一个资源在 2021 年 5 月 26 日上午 5:00 到上午 10:00 工作。 这些 API 仅支持此类型的发生,即在同一天开始和结束。 另一个示例,考虑一个资源从 2021 年 5 月 26 日晚上 8:00 到 2021 年 5 月 27 日上午 10:00 工作。 仅使用一个 msdyn_SaveCalendar API 调用无法创建此发生;您需要进行两次调用。

全天发生

当工作时间类型在一个或多个整天发生时,从开始日期的午夜(凌晨 12:00 点)开始,它成为全天发生。 全天发生的最大持续时间是五年。

例如,某个资源从 2021 年 5 月 26 日到 2021 年 5 月 30 日这一天结束为全天工作。 这是一个持续五天的全天发生。

每周定期发生

当一个工作时间类型在每周选定日期的同一个时间发生时,这称为每周定期发生

例如,资源在每周一、周二和周三的上午 5:00 到上午 10:00 工作。

每日定期发生

当一个工作时间类型每天在同一时间发生时,称为每日定期发生

例如,资源在一周中每一天的上午 5:00 到上午 10:00 工作。

自定义定期发生

当工作时间类型在一周的某些天的某些时间发生,但不同天的时间不同时,您可以创建自定义定期发生

例如,资源在每周一上午 5:00 到上午 10:00 以及每周三下午 12:00 到下午 3:00 工作。

工作时间类型

这些 API 支持以下工作时间类型的创建、更新和删除操作:

工作时间

工作时间是指实体可以执行工作的时间。

使用这些 API,您可以执行以下操作:

  • 创建、编辑或删除工作时间发生。
  • 创建、编辑或删除工作时间每日定期发生。
  • 创建、编辑或删除工作时间每周定期发生。
  • 创建、编辑或删除工作时间自定义定期发生。
  • 创建、编辑或删除全天工作时间。
  • 创建或编辑工作时间上的产能。
  • 编辑定期发生中的单个工作时间发生。
  • 在定期发生中编辑此发生及后来的发生
  • 将工作时间发生更改为定期发生。
  • 更改日历规则的时区。

使用此 API,您不能执行以下操作:

  • 从定期发生中删除单个工作时间发生。
  • 创建跨 24 小时但不在午夜(凌晨 12:00 点)开始和结束的发生。
  • 创建、编辑或删除全天定期发生。

非工作时间

这些是实体由于未指明原因而无法工作的时间。

使用这些 API,您可以执行以下操作:

  • 创建或编辑全天非工作时间。
  • 创建或编辑非工作时间发生。
  • 更改日历规则的时区。

使用这些 API,您不能执行以下操作:

  • 创建或编辑非工作时间定期发生。

中断

这些是工作日中实体在工间休息、没有工作的时间。 没有工作时间不会存在工间休息时间;它们必须在一天中的两个工作时间之间发生。 工间休息时间不能与工作时间重叠。

使用这些 API,您可以执行以下操作:

  • 在工作时间内创建或编辑工间休息时间。

使用这些 API,您不能执行以下操作:

  • 从工作时间的发生或定期发生中仅删除工间休息时间。

休息时间

这些是实体因休假而无法工作的时间。 可以指定休息时间的原因。

使用这些 API,您可以执行以下操作:

  • 使用标签创建或编辑休息时间。
  • 更改日历规则的时区。

使用这些 API,您不能执行以下操作:

  • 创建或编辑休息时间定期发生。

节假日

您可以创建节假日实体来定义歇业时间。 使用 msdyn_SaveCalendar API,您可以使用可选 ObserveClosure 键将每个实体设置为考虑或忽略组织的歇业时间。 当他们被设置为考虑这些歇业时,实体将无法工作。

保存日历 API

输入

请求只包含一个属性—CalendarEventInfo,它是一个字符串类型。 它包含所有嵌入在此字符串中的其他几个属性。

备注

在下表中,类型表示要成功发起请求所需要的格式。 但是,整个请求解析为单个字符串。

CalendarEventInfo

客户 类型 必填 说明
EntityLogicalName String 此键描述从其调用 API 的实体。 此实体的日历将创建或编辑。
CalendarId GUID 此键包含与上述实体相关的日历 ID。 创建这些实体中的任何一个时,还将自动创建日历记录。 这些 API 通过添加规则或编辑现有规则来编辑该日历记录。
RulesAndRecurrences RulesAndRecurrences 此键是一个数组,每个元素包含多个属性,如下一节的表中所列。 数组的大小应该至少为一。
IsVaried 布尔型 No 此键对于自定义定期发生场景应设置为 true
IsEdit 布尔型 No 此键对于编辑现有规则应设置为 true
TimeZoneCode 整型 No 此键采用与日历规则的时区相对应的整数值。 有关映射,请转到本文后面的时区代码。 默认值为用户的时区。
InnerCalendarDescription String No 仅当日历规则用于休息时间时才需要此键。 它应该包含休息时间的原因。
ObserveClosure 布尔型 No 此键特定于定期发生。 如果设置为 true,实体将考虑节假日。
RecurrenceEndDate 日期/时间 No 此键特定于定期发生。 包含定期发生的结束日期。 如果时间戳为 08:00:00 或更早,定期发生结束日期为指定日期的前一天。 如果时间戳为 08:00:01 或以后,日期保持不变。 发生的默认值为 null。 定期发生的默认值为 30 Dec 9999, 23:59:59 hours, UTC。
RecurrenceSplit 布尔型 No 此键特定于定期发生。 对于编辑定期发生的“此发生及后来的发生”,它将设置为 true
ResourceId GUID No 此键包含 SystemUserIdResourceId,仅在与此调用关联的实体是 SystemUser 类型的可预订资源时传递。 这是在服务管理选项卡上检查 OwnCalendar 特权所必需的。
UseV2 标记 No 传递此标志将启用工作时间日历 V2 版本,并启用允许多个定期发生的增强重叠规则逻辑。 有关详细信息,请参阅如果存在重叠的规则,会发生什么情况?

RulesAndRecurrences

客户 类型​​ 必需 说明
规则 规则 此键是一个数组,每个元素包含多个属性,如下一节的表中所列。 数组的大小应该至少为一。
RecurrencePattern String No 此键特定于定期发生。 我们当前仅支持此模式:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU,MO,TU,WE,TH,FR,SABYDAY 可以更改为包括更少的天数;但是,FREQINTERVAL 不能更改。
InnerCalendarId GUID No 此键特定于编辑。 如果正在编辑规则,需要在此处传递 InnerCalendarId。 如果未传递 InnerCalendarId,即使 IsEdit 键设置为 true,API 也会创建新规则。
操作​ 整型 No 此键特定于自定义定期发生。 如果正在创建或编辑自定义定期发生,应输入以下数字之一:
  • (1) 向定期发生添加天
  • (2) 从定期发生中删除天
  • (3) 仅编辑开始日期或结束日期或时间,或编辑产能
  • (4) 编辑除 (3) 中提到的键之外的任何内容

规则

客户 Type 需要 描述
StartTime 日期/时间 此键包含 ISO 格式的日期/时间条目。 例如,\"2021-05-15T12:00:00.000Z\"。 时间部分确定前面指定的时区中工作时间的开始时间。 日期部分确定工作时间的开始日期。 这里,2021 年 5 月 15 日是发生的日期或定期发生的开始日期。 如果模式为 BYDAY=TU,WE,但日期为 5 月 15 日(星期六),API 将自动为 5 月 15 日之后的所有星期二和星期三创建或编辑规则。 在这种情况下,规则不必具有与那一天对应的日期。
EndTime 日期/时间 它包含 ISO 格式的日期/时间条目。 例如,\"2021-05-15T12:00:00.000Z\"。 时间部分确定前面指定的时区中工作时间的结束时间。 日期部分必须包含与 StartTime 的日期部分相同的日期。 唯一的例外情况是:
  • 如果它是全天发生。 在这种情况下,日期部分应反映全天发生的结束日期。
  • 发生在一天结束时结束,即第二天的凌晨 12:00。 在这种情况下,日期应为 \"2021-05-16T00:00:00.000Z\"。 要指定定期发生的结束日期,请修改 RecurrenceEndDate 属性。
WorkHourType 整型 此键包含与以下选项之一对应的数字:
  • (0) 工作时间
  • (1) 工间休息时间
  • (2) 非工作时间
  • (3) 休息时间
精力 整型 No 此键确定实体的产能。 它必须是整数。 默认值为 1。

输出

此 POST API 为所选实体创建或修改日历规则记录。 它还提供以下输出。

客户 类型 说明
InnerCalendarIds String 一组 InnerCalendarIds GUID,是 POST 操作的结果。

删除日历 API

输入

客户 类型 必填 说明
EntityLogicalName String 此字段描述要删除其日历规则的实体。
InnerCalendarId GUID 此字段描述需要删除的 InnerCalendarId 的 ID。 如果有多个 InnerCalendarIds 与单个规则关联,此处的任何一个 ID 就够。 有关内部日历和外部日历的详细信息:日历实体
CalendarId GUID 此字段描述实体的 CalendarId
IsVaried 布尔型 No 此字段特定于定期发生,如果自定义定期发生规则被删除,将设置为 yes
UseV2 标记 No 传递此标志将启用工作时间日历 V2 版本,并启用允许多个定期发生的增强重叠规则逻辑。 有关详细信息,请参阅如果存在重叠的规则,会发生什么情况?

输出

此 POST API 删除所选实体的日历规则记录。 此外,它还提供以下输出。

客户 Type 描述
InnerCalendarIds String 一组 InnerCalendarIds GUID,是 POST 操作的结果。

加载日历 API

输入

名称:msdyn_LoadCalendars
类型:操作
描述:返回给定 LoadCalendarsInput 的日历。

名称:msdyn_LoadCalendars.LoadCalendarsInput
类型:参数
描述:以下 JSON 格式的字符串:

{
   StartDate: string,
   EndDate: string,
   CalendarIds: string[]
}

名称:msdyn_LoadCalendarsResponse
类型:ComplexType
描述:包含来自 msdyn_loadCalendars 操作的响应。

名称:msdyn_LoadCalendarsResponse.CalendarEvents
类型:属性
描述:以下 JSON 格式的字符串:

{
"calendarId": CalendarEventSlot[]
}

其中 calendarId 是代表日历 Guid 的正确 guid,CalendarEventSlot 是以下格式的对象:

{
  CalendarId: string,
  InnerCalendarId: string,
  Start: string,
  End: string,
  Effort: double
}

如何调用 API

这些 API 可以使用浏览器调用。

  1. 打开浏览器和您需要在其中进行这些日历更改的组织。
  2. 打开开发人员工具(在 Microsoft Edge 中选择 Ctrl+Shift+I,在 Google Chrome 中选择 F12)。
  3. 在控制台中,将 [org-name] 替换为组织详细信息(例如,http://your_org.crm.dynamics.com)后,输入以下函数:
       function CalendarAction(action, data) {
           let req = new XMLHttpRequest();
           req.open("POST", "**[org-name]**/api/data/v9.0/" + action, true);
           req.setRequestHeader("OData-MaxVersion", "4.0");
           req.setRequestHeader("OData-Version", "4.0");
           req.setRequestHeader("Accept", "application/json");
           req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
           req.setRequestHeader("Prefer", 'odata.include-annotations="*"');
           req.onreadystatechange = function () {
               if (this.readyState === 4) {
                   req.onreadystatechange = null;
                   if(this.status == 200) {
                       console.log(JSON.parse(this.response));
                   } else {
                       console.error(JSON.parse(this.response));
                   }
               }
           };
           req.send(JSON.stringify(data));
       }
  1. 定义此函数后,您可以调用它来使用 API 创建、编辑或删除日历。 输入以下调用来保存日历:
       CalendarAction("msdyn_SaveCalendar",{
           "CalendarEventInfo":"{
               \"CalendarId\":\"df0857c4-50f5-4576-8e89-f236670ad2d5\",
               \"EntityLogicalName\":\"bookableresource\",
               \"TimeZoneCode\":92,\"StartDate\":\"2021-04-25T00:00:00.000Z\",
               \"IsVaried\":false,
               \"RulesAndRecurrences\":[{
                   \"Rules\":[{
                       \"StartTime\":\"2021-04-25T08:00:00.000Z\",
                       \"EndTime\":\"2021-04-25T17:00:00.000Z\",
                       \"Duration\":540,
                       \"Effort\":1
                   }]
               }]
           }"
       })

输入以下调用来删除日历:

       CalendarAction("msdyn_DeleteCalendar", {
           "CalendarEventInfo":"{
               \"CalendarId\":\"8390358c-77d0-430f-b176-f27adadac8eb\",
               \"EntityLogicalName\":\"bookableresource\",
               \"InnerCalendarId\":\"cf508c2c-5c55-485c-be1e-d2ebcb385441\"
           }"
       })
       

有关如何根据需要进行不同调用的示例,请参阅下一节。 将步骤 3 中函数调用的 action 替换为 msdyn_SaveCalendarmsdyn_DeleteCalendar,并将 data 替换为相关的 CalendarEventInfo

另请参见以下 msdyn_SaveCalendar 操作的 Power Automate 调用的屏幕截图:msdyn_SaveCalendar 操作的 Power Automate 调用。

API 使用示例场景

我们来演练一下您可以使用这些 API 的一些场景。

Bob 和 Tim 是位于华盛顿贝尔维尤的 Contoso Enterprises 的送货卡车司机。 他们的调度员 Debbie 负责更改他们的工作时间日历。 Debbie 使用 msdyn_SaveCalendarmsdyn_DeleteCalendar API 进行这些更改。

创建工作时间发生。

Bob 被安排于 2021 年 5 月 15 日上午 9:00 至下午 5:00 开车运送包裹。 Debbie 使用 msdyn_SaveCalendar API。

请求

{
 "CalendarEventInfo": "{\"CalendarId\":\"d33263c7-c16b-4e3e-a56a-20f7a66cafc1\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-05-15T09:00:00.000Z\",\"EndTime\":\"2021-05-15T17:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}]}]}"
}

Response

{
  "InnerCalendarIds": "[\"f76cc333-cbbe-eb11-a81d-000d3a6e4359\"]"
}

编辑工作时间发生。

之后,Bob 的日程安排更改为 2021 年 5 月 15 日上午 10:00 开始。 Debbie 使用 msdyn_SaveCalendar API。

请求

{
 "CalendarEventInfo": "{\"CalendarId\":\"d33263c7-c16b-4e3e-a56a-20f7a66cafc1\",\"EntityLogicalName\":\"bookableresource\",\"IsEdit\":\"true\",\"TimeZoneCode\":5,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-05-15T10:00:00.000Z\",\"EndTime\":\"2021-05-15T17:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}], \"InnerCalendarId\":\"f76cc333-cbbe-eb11-a81d-000d3a6e4359\"}]}"
}

Response

{
  "InnerCalendarIds": "[\"f76cc333-cbbe-eb11-a81d-000d3a6e4359\"]"
}

刪除工作时间发生。

由于家庭出现紧急情况,Bob 需要取消一整天的工作。 Debbie 使用 msdyn_DeleteCalendar API。

Request

{
 "CalendarEventInfo": "{\"CalendarId\":\"d33263c7-c16b-4e3e-a56a-20f7a66cafc1\",\"EntityLogicalName\":\"bookableresource\",\"InnerCalendarId\":\"f76cc333-cbbe-eb11-a81d-000d3a6e4359\"}"
}

响应

{
  "InnerCalendarIds": "[\"f76cc333-cbbe-eb11-a81d-000d3a6e4359\"]"
}

创建工作时间每日定期发生

从 2021 年 5 月 20 日开始,Bob 决定一整周从上午 8:00 到下午 5:00 在 Contoso 工作,并将于 2021 年 7 月 15 日停止在那里工作。

Request

{
 "CalendarEventInfo": "{\"CalendarId\":\"d33263c7-c16b-4e3e-a56a-20f7a66cafc1\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"RecurrenceEndDate\":\"2021-07-15T00:00:00.000Z\",\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-05-20T08:00:00.000Z\",\"EndTime\":\"2021-05-20T17:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=SU,MO,TU,WE,TH,FR,SA\"}]}"
}

响应

{
  "InnerCalendarIds": "[\"20f6cfa7-cfbe-eb11-a81d-000d3a6e4359\"]"
}

使用增加的产能编辑工作时间每日定期发生

Bob 决定在 2021 年 6 月 15 日这一整周停止工作以进行休息。 在那之前,Bob 将继续他之前同意的全周日程安排。 Debbie 使用 msdyn_SaveCalendar API 进行这些更改。

请求

{
 "CalendarEventInfo": "{\"CalendarId\":\"d33263c7-c16b-4e3e-a56a-20f7a66cafc1\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"RecurrenceEndDate\":\"2021-06-15T00:00:00.000Z\",\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-05-20T08:00:00.000Z\",\"EndTime\":\"2021-05-20T17:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"InnerCalendarId\":\"20f6cfa7-cfbe-eb11-a81d-000d3a6e4359\",\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=SU,MO,TU,WE,TH,FR,SA\"}]}"
}

Response

{
  "InnerCalendarIds": "[\"867a2461-cdbe-eb11-a81d-000d3a6e4359\"]"
}

创建工作时间每周定期发生

从 2021 年 6 月 16 日起,Bob 每周三和周五的工作时间为上午 8:00 至下午 5:00,他从中午 12:00 到中午 12:30 休息,吃午饭。 Debbie 使用 msdyn_SaveCalendar API,但犯了一个错误,将休息时间安排在中午 12:00 到下午 1:00。

Request

{
  "CalendarEventInfo": "{\"CalendarId\":\"d33263c7-c16b-4e3e-a56a-20f7a66cafc1\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-06-16T08:00:00.000Z\",\"EndTime\":\"2021-06-16T12:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}, {\"StartTime\":\"2021-06-16T12:00:00.000Z\",\"EndTime\":\"2021-06-16T13:00:00.000Z\",\"Effort\":null,\"WorkHourType\":1}, {\"StartTime\":\"2021-06-16T13:00:00.000Z\",\"EndTime\":\"2021-06-16T17:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=WE,TH,FR\"}]}"
}

响应

{
  "InnerCalendarIds": "[\"1f894441-d0be-eb11-a81d-000d3a6e4359\"]"
}

编辑工作时间每周定期发生的工间休息时间

然后 Debbie 更正了她的错误,使用 msdyn_SaveCalendar API 将工间休息时间更改为从中午 12:00 到中午 12:30 发生。

请求

{
  "CalendarEventInfo": "{\"CalendarId\":\"d33263c7-c16b-4e3e-a56a-20f7a66cafc1\",\"EntityLogicalName\":\"bookableresource\",\"IsEdit\":\"true\",\"TimeZoneCode\":5,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-06-15T08:00:00.000Z\",\"EndTime\":\"2021-06-15T12:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}, {\"StartTime\":\"2021-06-15T12:00:00.000Z\",\"EndTime\":\"2021-06-15T12:30:00.000Z\",\"Effort\":null,\"WorkHourType\":1}, {\"StartTime\":\"2021-06-15T12:30:00.000Z\",\"EndTime\":\"2021-06-15T17:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"InnerCalendarId\":\"1f894441-d0be-eb11-a81d-000d3a6e4359\",\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=WE,TH,FR\"}]}"
}

Response

{
  "InnerCalendarIds": "[\"1f894441-d0be-eb11-a81d-000d3a6e4359\"]"
}

创建工作时间自定义定期发生

Tim 在星期一的上午 8:00 到下午 5:00 以及星期三的上午 11:00 到下午 3:00 为 Contoso 工作。 Tim 于 2021 年 5 月 16 日开始为 Contoso 工作。 Debbie 使用 msdyn_SaveCalendar API 创建 Tim 的工作时间。

请求

{
"CalendarEventInfo": "{\"CalendarId\":\"a68245c9-ba2e-4496-9c18-3bee75fda396\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"IsVaried\":true,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-05-16T08:00:00.000Z\",\"EndTime\":\"2021-05-16T17:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"Action\":1,\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=MO\"},{\"Rules\":[{\"StartTime\":\"2021-05-16T11:00:00.000Z\",\"EndTime\":\"2021-05-16T15:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"Action\":1,\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=WE\"}]}"
}

Response

{
  "InnerCalendarIds": "[\"9fb8c199-d1be-eb11-a81d-000d3a6e4359\", \"a2b8c199-d1be-eb11-a81d-000d3a6e4359\"]"
}

编辑工作时间自定义定期发生

之后,Tim 的日程安排发生了变化:工作时间是星期三下午 5:00 至晚上 8:00,星期四上午 10:00 至中午 12:00。 星期一被从 Tim 的日程安排中删除。 Debbie 使用 msdyn_SaveCalendar API 达到此目的。

Request

{
"CalendarEventInfo": "{\"CalendarId\":\"a68245c9-ba2e-4496-9c18-3bee75fda396\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"IsVaried\":true,\"IsEdit\":true,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-05-16T08:00:00.000Z\",\"EndTime\":\"2021-05-16T17:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"Action\":2,\"InnerCalendarId\":\"9fb8c199-d1be-eb11-a81d-000d3a6e4359\",\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=MO\"},{\"Rules\":[{\"StartTime\":\"2021-05-16T17:00:00.000Z\",\"EndTime\":\"2021-05-16T20:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"Action\":3,\"InnerCalendarId\":\"a2b8c199-d1be-eb11-a81d-000d3a6e4359\",\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=WE\"}, {\"Rules\":[{\"StartTime\":\"2021-05-16T10:00:00.000Z\",\"EndTime\":\"2021-05-16T12:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}],\"Action\":1,\"InnerCalendarId\":null,\"RecurrencePattern\":\"FREQ=WEEKLY;INTERVAL=1;BYDAY=TH\"}]}"
}

响应

{
  "InnerCalendarIds": "[\"a2b8c199-d1be-eb11-a81d-000d3a6e4359\", \"942bda0f-d3be-eb11-a81d-000d3a6e4359\"]"
}

编辑定期发生中的工作时间发生

2021 年 5 月 26 日,Tim 只能在下午 1:00 到晚上 7:00 之间工作。 Debbie 在这里使用 msdyn_SaveCalendar API。

Request

{
 "CalendarEventInfo": "{\"CalendarId\":\"a68245c9-ba2e-4496-9c18-3bee75fda396\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-05-26T13:00:00.000Z\",\"EndTime\":\"2021-05-26T19:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}], \"InnerCalendarId\":\"a2b8c199-d1be-eb11-a81d-000d3a6e4359\"}]}"
}

响应

{
  "InnerCalendarIds": "[\"a2b8c199-d1be-eb11-a81d-000d3a6e4359\"]"
}

刪除工作时间自定义定期发生

Tim 决定离开公司,并且必须删除他们的整个日程安排。 Debbie 在这里使用 msdyn_DeleteCalendar API。

Request

{
 "CalendarEventInfo": "{\"CalendarId\":\"a68245c9-ba2e-4496-9c18-3bee75fda396\",\"EntityLogicalName\":\"bookableresource\",\"InnerCalendarId\":\"34d2210c-9fb6-eb11-a820-000d3afb1dba\",\"IsVaried\":true}"
}

响应

{
  "InnerCalendarIds": "[\"a2b8c199-d1be-eb11-a81d-000d3a6e4359\", \"942bda0f-d3be-eb11-a81d-000d3a6e4359\"]"
}

创建休息时间

从 2021 年 6 月 9 日起,Tim 将请三天假,参加家庭度假。

请求

{
 "CalendarEventInfo": "{\"CalendarId\":\"a68245c9-ba2e-4496-9c18-3bee75fda396\",\"InnerCalendarDescription\":\"Family Vacation\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-06-15T00:00:00.000Z\",\"EndTime\":\"2021-06-17T00:00:00.000Z\",\"Effort\":1,\"WorkHourType\":3}]}]}"
}

Response

{
  "InnerCalendarIds": "[\"266c434e-d5be-eb11-a81d-000d3a6e4359\"]"
}

创建全天工作时间

从 2021 年 5 月 20 日开始,Tim 有一个 72 小时轮班。 Debbie 使用 msdyn_SaveCalendar API 创建 Tim 的工作时间。

Request

{
 "CalendarEventInfo": "{\"CalendarId\":\"a68245c9-ba2e-4496-9c18-3bee75fda396\",\"EntityLogicalName\":\"bookableresource\",\"TimeZoneCode\":5,\"RulesAndRecurrences\":[{\"Rules\":[{\"StartTime\":\"2021-05-20T00:00:00.000Z\",\"EndTime\":\"2021-05-22T00:00:00.000Z\",\"Effort\":1,\"WorkHourType\":0}]}]}"
}

响应

{
  "InnerCalendarIds": "[\"6e160a8e-d5be-eb11-a81d-000d3a6e4359\"]"
}

常见问题解答

我收到错误“开始时间不能大于或等于结束时间。”

确保不同日历规则的时隙中没有重叠。 检查日期,确保 StartTime 不晚于 EndTime。 同时,验证时间是否采用 24 小时制。

API 是否可用于更新“工作小时模板”实体?

可以,除资源工作时间外,您还可以使用此 API 创建和更新工作时间模板。

我收到错误“在反序列化类型 Microsoft.Dynamics.UCICalendar.Plugins.SaveCalendarContract+CalendarEventInfo 的对象时出现错误。 输入源未正确格式化。
或者
预期状态为“Element”。 遇到名称为“namespace”的“Text”。

请确保字符串解析正确。 可能缺少括号、逗号或分号。

我收到错误“无效的定期模式。 有关支持的语言,请参阅本文档。”

我们当前仅支持此模式:FREQ=DAILY;INTERVAL=1;BYDAY=SU,MO,TU,WE,TH,FR,SABYDAY 可以更改为包括更少的天数;但是,FREQINTERVAL 不能更改。 请确保模式中没有空格。

如何获取资源的 CalendarId 和 InnerCalendarId 的信息?

CalendarId 可以从资源属性中检索。 进行此调用以获取此信息:[org-url]/api/data/v9.1/bookableresources([bookableresourceGUID])

上一个调用的示例将为 [org-url]/api/data/v9.1/bookableresources(7bb0224b-6712-ec11-94f9-000d3a6d888e)

InnerCalendarId 可以从日历属性中检索。 进行此调用以获取此信息:[org-url]/api/data/v9.1/calendars([calendar-id-from-above-call])?$expand=calendar_calendar_rules

上一个调用的示例为 [org-url]/api/data/v9.1/calendars(02481736-1b6a-4d49-9ebd-a5bd041c1c99)?$expand=calendar_calendar_rules

如果存在重叠的规则,会发生什么情况?

规则分为几个不同的等级:

  • 等级 1 - 每日出现(工作/非工作)和休息时间出现。
  • 等级 0 - 每周定期(工作/非工作)。

V2 重叠规则

  • 等级 1 规则比等级 0 规则具有更高的优先级。 如果同一天有两个规则(每个等级一个),则每日出现或休息时间出现将优先于每周定期。
  • 当同一日期范围内有多个等级 0 规则时:
    • 如果时间不相交,则都会保留在日历上。
    • 如果时间相交,则最近创建/修改的规则被视为资源日历的规则。 将删除日期范围中所有其他相交规则。 如果某些等级 0 规则在某些日期相交,但在其他日期不相交,这规则将进行切片以保留不相交部分,同时删除相交部分。

V2 日历行为的示例:

示例 1 - 重复工作时间:天数/时间不重叠的重叠日期

对于给定日期范围,技术人员可以在不同日期上午班、下午班或夜班工作。

  1. 为给定日期范围创建第一个重复日历规则。 例如:Repeat Mon, Tue; 1.1-4.1; 8am-5pm ET

  2. 为相交日期范围创建第二个重复日历规则,同时确保工作时间不与以前天数或时间相交。 例如:Repeat Wed, Thu; 1.1-4.1; 8am-5pm ETRepeat Mon, Tue; 1.1-4.1; 5pm-8pm ET

结果:两个日历规则保留并共存。

示例 2 - 重复工作时间:部分日期重叠,所有重叠的日期和第二个规则都在第一个规则之前或之后开始/结束

技术人员获得新工作计划,取代了旧计划的某些周。 按合同,他们每周的工作日期始终相同。

  1. 为给定日期范围创建第一个重复日历规则。 例如:Repeat Mon, Tue; 2.1-4.1; 8am-5pm ET

  2. 为重叠的日期范围创建第二个重复日历规则,其中所有日期均具有重叠的工作时间。 为新规则选择在第一个规则的开始/结束日期之前或之后的开始/结束日期。 例如:Repeat Mon, Tue; 3.1-5.1; 1pm-8pm ET

结果:第一个规则被截断以容纳第二个规则的开始日期/结束日期。 例如:Repeat Mon, Tue; 2.1-2.28; 8am-5pm ET AND Repeat Mon, Tue; 3.1-5.1; 1pm-8pm ET

示例 3 - 重复工作时间:所有重叠日期,不分天数/时间重叠

该技术人员是一名固定期限为 2 个月的合同工作人员。 他们已同意某些日期加班。 他们希望将星期二的工作时间转移到较早时间/稍后时间。

  1. 为给定日期范围创建一些重复日历规则。 例如:Repeat Mon, Tue; 2.1-4.1; 8am-12pm ET AND Repeat Tue, Wed; 2.1-4.1, 1pm-5pm ET

  2. 为同一个日期范围创建一个新的重复日历规则。 选择与原始规则部分重叠的天数/时间。 例如:Repeat Tue,Thurs ; 2.1-4.1; 10am-2pm ET

结果:新规则会覆盖存在重叠的旧规则,并保留其他规则不变。 例如:Repeat Mon; 2.1-4.1; 8am-12pm ET AND Repeat Wed; 2.1-4.1; 1pm-5pm ET AND Repeat Tue,Thurs ; 2.1-4.1; 10am-2pm ET

示例 4 - 重复工作时间:旧规则中包含新规则日期,某些日期/时间重叠

一位技术人员的工作时间为每周的周一到周五上午 8 点至下午 5 点。 就过来两周,他们需要每周一到周四上午 6 点到下午 6 点处理特殊紧急项目。

  1. 为给定日期范围创建第一个重复日历规则。 例如:Repeat Mon,Tue,Wed,Thu,Fri; 1.1-No End Date; 8am-5pm ET

  2. 创建第二个重复日历,该日历包含在上面的日期范围内,然后选择某些日期重叠的工作时间。 例如:Repeat Mon,Tue,Wed; 5.1-5.14; 6am-6pm ET

结果:在本练习结束时,日历应包含四个重复规则:

  • 将第一个规则截断为第二个规则的开始日期
  • 第二个日历规则
  • 创建类似于第一个规则但具有非重叠日期的第二个规则的日期的新规则
  • 将第一个规则截断以从第二个规则的结束日期开始,并且无结束日期

例如:Repeat Mon,Tue,Wed,Thu,Fri; 1.1–4.30; 8am-5pm ET AND Repeat Mon,Tue,Wed; 5.1-5.14; 6am-6pm ET AND Repeat Thu,Fri, 5.1-5.14; 8am-5pm ET AND Repeat Mon,Tue,Wed,Thu,Fri; 5.15–No End Date; 8am-5pm ET

示例 5 - 非重复工作时间(重复,等级 1 规则)

一个技术人员有大量团队合作日期,这些日期优先于当天的所有其他工作时间实例。

  1. 为给定日期范围创建一个重复日历规则。 例如:Repeat Mon,Tue,Wed,Thu,Fri; 1.1-No End Date; 8am-5pm ET

  2. 创建包含在以上日期范围内的非重复日历规则。 选择在某些日期重叠的工作时间。 例如:Non-repeat; 6.21; 7am-1pm ET

结果:在本练习结束时,日历应包含一个非重复规则(发生)。 不重复规则将覆盖全天的重叠重复事件。 例如:Repeat Mon,Tue,Wed,Thu,Fri; 1.1-No End Date except 6.21; non-repeat; 6.21; 7am-1pm ET

V1 重叠规则

  • 等级 1 规则比等级 0 规则具有更高的优先级。 因此,如果同一天有两个规则(每个等级一个),则每日出现或休息时间出现将优先于每周定期。
  • 如果存在同一等级的两个规则,最近创建/修改的规则将视为资源的日历。
  • 请记住,全天出现属于等级 1,因此您可能要考虑将其更改为每周定期,以便能够添加出现工作时间并使这些时间得到遵守。
  • 当存在工作时间并且创建了与它重叠的休息时间出现时,规则将按以下方式拆分:确保遵守休息时间,作为工作时间的任何剩余时间将保持原样。 例如,如果 9 月 21 日 8 AM 到 5 PM 是工作时间,并且在 9 月 21 日添加了从 3 PM 到 7 PM 的休息时间出现,这将解析为工作时间为 8 PM 到 3 PM,休息时间从 3 PM 到 7 PM。 但是,如果按相反顺序(首先创建休息时间,然后创建工作时间)创建了规则,无论时隙如何,将仅重新选择工作时间。 将覆盖休息时间。

时区代码

枚举 时区
12 (GMT-12:00)国际日期变更线西
1 (GMT+13:00)萨摩亚群岛
2 (GMT-10:00)夏威夷
3 (GMT-09:00)阿拉斯加
4 (GMT-08:00)太平洋时间(美国和加拿大)
5 (GMT-08:00)下加利福尼亚
6 (GMT-11:00) 协调世界时-11
7 (GMT-10:00) 阿留申群岛
8 (GMT-09:30) 马克萨斯群岛
9 (GMT-09:00) 协调世界时-09
10 (GMT-07:00)山地时间(美国和加拿大)
11 (GMT-08:00) 协调世界时-08
12 (GMT-07:00)奇瓦瓦,拉巴斯,马扎特兰
15 (GMT-07:00)亚利桑那
20 (GMT-06:00)中部时间(美国和加拿大)
25 (GMT-06:00)萨斯喀彻温
29 (GMT-06:00)瓜达拉哈拉,墨西哥城,蒙特雷
33 (GMT-06:00)中美洲
34 (GMT-06:00) 复活节岛
35 (GMT-05:00)东部时间(美国和加拿大)
40 (GMT-05:00)印地安那(东部)
43 (GMT-05:00) 海地
44 (GMT-05:00) 哈瓦那
45 (GMT-05:00)波哥大,利马,基多,里奥布朗库
47 (GMT-04:00) 加拉加斯
50 (GMT-04:00)大西洋时间(加拿大)
51 (GMT-05:00)特克斯和凯科斯群岛
55 (GMT - 04:00)乔治敦,拉巴斯,圣胡安
56 (GMT-04:00)圣地亚哥
58 (GMT-04:00)库亚巴
59 (GMT - 04:00)亚松森
60 (GMT-03:30)纽芬兰
65 (GMT-03:00)巴西利亚
69 (GMT - 03:00)布宜诺斯艾利斯
70 (GMT-03:00)卡宴,福塔雷萨
71 (GMT-03:00)萨尔瓦多
72 (GMT-03:00) 圣皮埃尔和密克隆群岛
73 (GMT-03:00)格陵兰
74 (GMT - 03:00)蒙得维的亚
75 (GMT-02:00)中大西洋
76 (GMT-02:00)协调世界时-02
77 (GMT-03:00) 阿拉瓜伊纳
80 (GMT-01:00)亚速尔群岛
83 (GMT-01:00)佛得角
84 (GMT+01:00) 卡萨布兰卡
85 (GMT+00:00) 都柏林,爱丁堡,里斯本,伦敦
90 (GMT+00:00) 蒙罗维亚,雷克雅未克
92 (GMT)协调世界时
95 (GMT+01:00)贝尔格莱德,布拉迪斯拉发,布达佩斯,卢布尔雅那,布拉格
100 (GMT+01:00)萨拉热窝,斯科普里,华沙,萨格勒布
105 (GMT+01:00)布鲁塞尔,哥本哈根,马德里,巴黎
110 (GMT+01:00)阿姆斯特丹,柏林,伯尔尼,罗马,斯德哥尔摩,维也纳
113 (GMT+01:00)中非西部
115 (GMT+02:00) 基希讷乌
120 (GMT+02:00)开罗
125 (GMT+02:00)赫尔辛基,基辅,里加,索非亚,塔林,维尔纽斯
129 (GMT+02:00)安曼
130 (GMT+02:00)雅典,布加勒斯特
131 (GMT+02:00)贝鲁特
133 (GMT+02:00)大马士革
134 (GMT+03:00)伊斯坦布尔
135 (GMT+02:00)耶路撒冷
140 (GMT+02:00)哈拉雷,比勒陀利亚
141 (GMT+02:00)温得和克
142 (GMT+02:00)加沙,希伯伦
145 (GMT+03:00)莫斯科,圣彼得堡
150 (GMT+03:00)科威特,利雅得
151 (GMT+03:00)明斯克
155 (GMT+03:00)内罗毕
158 (GMT+03:00)巴格达
159 (GMT+02:00) 加里宁格勒
160 (GMT+03:30)德黑兰
165 (GMT+04:00)阿布扎比,马斯喀特
169 (GMT+04:00)巴库
170 (GMT+04:00)埃里温
172 (GMT+04:00)路易港
173 (GMT+04:00)第比利斯
174 (GMT+04:00) 伊热夫斯克,萨马拉
175 (GMT+04:30)喀布尔
176 (GMT+04:00) 阿斯特拉罕,乌里扬诺夫斯克
180 (GMT+05:00)叶卡捷琳堡
184 (GMT+05:00)伊斯兰堡,卡拉奇
185 (GMT+05:00)塔什干
190 (GMT+05:30)钦奈,加尔各答,孟买,新德里
193 (GMT+05:45)加德满都
195 (GMT+06:00)阿斯塔纳
196 (GMT+06:00)达卡
197 (GMT+06:00)鄂木斯克
200 (GMT+05:30)斯里加亚渥登普拉
201 (GMT+07:00)新西伯利亚
203 (GMT+06:30)仰光
205 (GMT+07:00)曼谷,河内,雅加达
207 (GMT+07:00)克拉斯诺亚尔斯克
208 (GMT+07:00) 巴尔瑙尔,戈尔诺-阿尔泰斯克
209 (GMT+07:00) 科布多
210 (GMT+08:00)北京,重庆,香港特别行政区,乌鲁木齐
211 (GMT+07:00) 托木斯克
215 (GMT+08:00)吉隆坡,新加坡
220 (GMT+08:00)台北
225 (GMT+08:00)珀斯
227 (GMT+08:00) 伊尔库茨克
228 (GMT+08:00)乌兰巴托
229 (GMT+09:00)平壤
230 (GMT+09:00)首尔
231 (GMT+08:45) 尤克拉
235 (GMT+09:00)大阪,札幌,东京
240 (GMT+09:00)雅库茨克
241 (GMT+09:00) 赤塔市
245 (GMT+09:30)达尔文
250 (GMT+09:30)阿德莱德
255 (GMT+10:00)堪培拉,墨尔本,悉尼
260 (GMT+10:00)布里斯班
265 (GMT+10:00)霍巴特
270 (GMT+10:00)符拉迪沃斯托克
274 (GMT+10:30) 豪勋爵岛
275 (GMT+10:00)关岛,莫尔兹比港
276 (GMT+11:00) 布干维尔岛
277 (GMT+11:00) 诺福克岛
278 (GMT+11:00) 萨哈林
279 (GMT+11:00) 乔库尔达赫
280 (GMT+11:00)所罗门群岛,新喀里多尼亚
281 (GMT+11:00) 马加丹
284 (GMT+12:00)协调世界时+12
285 (GMT+12:00)斐济
290 (GMT+12:00)奥克兰,惠灵顿
295 (GMT+12:00) 阿纳德尔,堪察加彼得罗巴甫洛夫斯克
299 (GMT+12:45) 查塔姆群岛
300 (GMT+13:00)努库阿洛法
301 (GMT-05:00)切图马尔
302 (UTC+02:00)喀土木
303 (GMT-03:00)彭塔阿雷纳斯
304 (GMT+04:00)伏尔加格勒
305 (GMT-07:00)育空