# Calendar Ops Skill

> 当用户要对真实日历数据做查询或增删改时触发：看今天/本周安排、查冲突、建会议、改时间、删日程。典型说法"我明天几点开会"、"帮我约 xx"、"schedule a meeting"。**不用于**：对话里口头提到时间或倒计时（→直接回答）、周期性后台任务如"每天 9 点跑脚本"（→schedule-ops-skill）。

- Skill: `openloaf/calendar-ops-skill` (Agent Skill)
- Install (CLI): `npx skillmds@latest add openloaf/calendar-ops-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/openloaf/calendar-ops-skill/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: openloaf (https://skillmd.com/u/openloaf)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/openloaf/calendar-ops-skill

---


# 日历操作技能

## 工具清单

| 工具 | 职责 | 只读 |
|------|------|------|
| `CalendarQuery` | 查询日历源 / 日程项目（mode: `list-sources` / `list-items` / `get-event` 等） | 是 |
| `CalendarMutate` | 创建 / 更新 / 删除日程（`kind: event` 或 `reminder`） | 否 |

> **加载**：全部为 deferred 工具，调用前须先 `ToolSearch(names: "CalendarQuery,CalendarMutate")` 激活 schema。

## 决策流程：用户想做什么？

### 路径 A — 查看日程 / 判断是否有空

1. **先拿时间基准**：用 `Bash` 执行 `date '+%Y-%m-%dT%H:%M:%S%z'` 获取当前时刻和时区。
   为什么？因为"今天""下周二"这类相对时间必须锚定到具体时区才有意义——"上午 10 点"对北京和纽约的人是完全不同的时刻，ISO 8601 不带时区偏移会导致静默错位。
2. **查日程**：用 `CalendarQuery`（mode: `list-items`），传入 `rangeStart` / `rangeEnd`（ISO 8601 **必须带时区偏移**，如 `+08:00`）。
   如果用户只说"看看今天的安排"，范围就是今天 00:00:00 到 23:59:59；如果说"这周有什么"，范围扩展到整周。宁可查宽一点也不要漏掉边界上的事件。
3. **按时间排序展示**，标注冲突和空闲段。用户问"我有空吗"时，从查询结果反推空闲区间即可。
4. 如果跨多个日历源，可传 `sourceIds` 过滤特定日历，避免混入不相关的日程（如节假日日历）。

### 路径 B — 创建日程或提醒

为什么创建前必须检测冲突？因为双重预订浪费所有人的时间，还让用户显得不专业。

1. **获取 sourceId**：先 `CalendarQuery`（mode: `list-sources`）拿到可用日历源列表。
   为什么？创建时 `sourceId` 是必填字段，凭空猜测 ID 必定失败。如果对话上文已经获取过 sourceId 且确信仍有效，可以复用。
2. **查冲突**：用 `CalendarQuery`（mode: `list-items`）查目标时间段是否已有安排。
3. **有冲突** → 告知用户冲突详情，建议替代时段。**绝不自作主张跳过冲突直接创建。**
   好的做法是推荐冲突前后最近的空闲段，让用户一键选择。
4. **无冲突** → 用 `CalendarMutate`（action: `create`）创建。
   `kind` 二选一：`event`（有明确开始/结束时间的日程）或 `reminder`（提醒事项，更适合待办性质的内容）。

### 路径 C — 修改日程

1. **先查到目标**：用 `CalendarQuery`（mode: `list-items`）搜索，确认 `itemId`。
   为什么？用户说"把下午的会改到 3 点"，你需要先精确定位到具体哪条日程，模糊匹配可能改错条目。
2. **如果涉及时间变更**，检查新时间段是否有冲突——理由同路径 B。
3. 用 `CalendarMutate`（action: `update`），传 `itemId` + 要改的字段。只传需要改的字段，不要把所有字段重新提交。

### 路径 D — 删除日程

1. 先查到目标，确认 `itemId`。
2. **向用户确认后**再执行 `CalendarMutate`（action: `delete`）。
   删除不可逆，必须让用户明确同意。如果有多条相似日程，列出候选让用户选择。

### 路径 E — 标记完成/未完成

用 `CalendarMutate`（action: `toggle-completed`），传 `itemId` + `completed` 布尔值。主要适用于 `reminder` 类型的日程项。

## 常见陷阱

### 时区混乱（最高频错误）

所有时间**必须**使用 ISO 8601 且**带时区偏移**（如 `+08:00`、`-05:00`）。永远先用 `Bash` 执行 `date` 确定当前时间和时区，不要假设 UTC 或任何默认值。一个不带偏移的 `2026-03-20T10:00:00` 会被不同系统解读为不同时刻，导致日程出现在错误的时间。

### 相对时间引用

"下周二""后天下午""这个月底"——先用 `Bash` 执行 `date` 获取当前时间，再自己计算出绝对时间。注意"下周二"在周一和周三说出来指的是不同的日期；跨月、跨年边界也容易算错。遇到含糊表达时主动向用户确认。

### 忘记查 sourceId

`CalendarMutate` 的 `create` 动作**要求** `sourceId`。不先调 `list-sources` 就创建 = 必然报错。用户可能有多个日历源（工作、个人、共享），要选对目标日历。

### 全天事件

全天事件需要设置 `allDay: true`。起止时间仍需提供，用当天 00:00:00 到 23:59:59（带时区偏移）。

### 查询范围过窄

用户说"最近有什么安排"时不要只查当天。根据语境适当扩大范围（未来 3-7 天），然后按日分组展示，让用户一目了然。

### 多条相似日程

用户说"删掉那个会议"但查询结果有多条匹配时，**必须列出候选让用户选择**，不要猜测。猜错删错的代价远高于多问一句。修改场景同理。

### 创建时遗漏关键信息

用户说"帮我约个会"但没说时间、地点、参会人——不要用默认值填充，主动追问缺失的关键字段。一个不完整的日程比没有日程更容易造成混乱。

## 工具速查

| 工具 | 用途 |
|------|------|
| `CalendarQuery` | 两种模式：`list-sources` 查日历源列表、`list-items` 按时间范围查日程项 |
| `CalendarMutate` | 四种动作：`create` 创建、`update` 修改、`delete` 删除、`toggle-completed` 切换完成 |

`CalendarMutate` 创建时的 `kind` 字段：`event`（日程事件）或 `reminder`（提醒事项）。

