如何合并Google Calendar API Freebusy请求中多个日历的响应?
合并Google Calendar Freebusy多日历响应的方法
嘿,这个问题我之前处理过,核心就是把各个日历的忙时条目提取出来,再合并掉重叠或连续的时间段就行。我给你一步步拆解:
步骤1:提取所有日历的忙时条目
首先从API返回的响应里,遍历calendars对象下的每个日历,把它们的busy数组全部收集到一个统一的大数组中。用JavaScript实现的话,代码大概是这样:
// 假设apiResponse是你拿到的API响应数据 const allBusySlots = []; for (const calendarId in apiResponse.calendars) { // 避免某个日历没有忙时数据导致报错 if (apiResponse.calendars[calendarId].busy) { allBusySlots.push(...apiResponse.calendars[calendarId].busy); } }
这一步完成后,你就得到了所有日历的忙时集合,但里面可能存在重叠的时间段,接下来需要处理合并逻辑。
步骤2:按开始时间排序
合并重叠时间段的前提是先把所有条目按start时间从小到大排序,这样我们可以逐个顺序处理:
// 按ISO时间字符串排序,直接比较也可以,不过转成Date对象更稳妥 allBusySlots.sort((a, b) => new Date(a.start) - new Date(b.start));
步骤3:合并重叠/连续的时间段
遍历排序后的数组,逐个检查当前时间段和已合并列表的最后一个时间段是否重叠或连续——如果是就更新合并,否则直接加入列表:
const mergedBusySlots = []; for (const slot of allBusySlots) { const currentStart = new Date(slot.start); const currentEnd = new Date(slot.end); // 合并列表为空时,直接加入第一个条目 if (mergedBusySlots.length === 0) { mergedBusySlots.push({ start: slot.start, end: slot.end }); continue; } // 取出合并列表的最后一个条目 const lastSlot = mergedBusySlots[mergedBusySlots.length - 1]; const lastEnd = new Date(lastSlot.end); // 当前时间段的开始时间 <= 上一个时间段的结束时间,说明重叠或连续,合并 if (currentStart <= lastEnd) { // 更新结束时间为两者中更晚的那个 lastSlot.end = lastEnd > currentEnd ? lastSlot.end : slot.end; } else { // 无重叠,直接加入列表 mergedBusySlots.push({ start: slot.start, end: slot.end }); } }
最终效果
现在mergedBusySlots就是合并后的统一忙时列表了,格式和单个日历的busy数组完全一致,方便后续使用。
举个实际例子:
- 日历1的忙时:
[{start: "2018-04-16T01:00:00Z", end: "2018-04-16T02:00:00Z"}, {start: "2018-04-16T04:00:00Z", end: "2018-04-16T05:00:00Z"}] - 日历2的忙时:
[{start: "2018-04-16T01:30:00Z", end: "2018-04-16T03:00:00Z"}]
合并后会变成:[{start: "2018-04-16T01:00:00Z", end: "2018-04-16T03:00:00Z"}, {start: "2018-04-16T04:00:00Z", end: "2018-04-16T05:00:00Z"}]
几个注意细节
- 确保API请求的
items数组包含了所有你需要的日历ID,否则响应里不会出现对应日历的忙时数据 - Google返回的时间是ISO 8601格式,用
new Date()可以直接解析,不用担心格式问题 - 部分日历可能没有忙时,此时
busy字段可能为空或不存在,代码里的判断可以避免报错
内容的提问来源于stack exchange,提问作者Kenmore
相关产品推荐
相关产品推荐

