Loading... # Daniel Calendar:一套自建、跨平台且可被 AI 理解的个人日历 大学生活里的时间表通常分散在很多地方:教务系统里的课程、手机中的临时安排、电脑上的项目 Deadline,以及 AI 对话中正在推进的工作。Daniel Calendar 是一个面向个人使用的私人日程服务,希望把这些内容收回到同一个可控的数据源中。 它并不试图重新发明一款日历客户端,而是选择开放的 **CalDAV** 协议作为核心:iPhone、iPad、macOS、Android 和其他支持 CalDAV 的客户端,都可以连接到同一份日历数据。网页端负责日历管理、账户配置与 AI 访问授权;AI 则通过受控 API 读取或创建日程。 > 这是一个私人、非营利的服务。账户注册采用邀请码机制,日历数据始终保存在自己的服务器中。 **网站首页可以在[这里](https://calendar.hdaniel.studio)看到。**  ## 产品概览 ```mermaid flowchart TB source["课程表、日常安排、项目 Deadline"] --> calendar["Daniel Calendar"] calendar --> caldav["CalDAV 服务"] caldav --> ios["iPhone 与 iPad 系统日历"] caldav --> mac["macOS 日历"] caldav --> android["Android CalDAV 客户端"] calendar --> portal["Web Portal"] portal --> manage["日历管理、账户与设置"] calendar --> api["受控 API"] api --> codex["Codex 与 AI Assistant"] ``` Daniel Calendar 的核心原则很简单:**服务器负责存储与同步,用户继续使用自己习惯的客户端。** 这样做有两个好处:一是日历不会被某一个网页或 App 绑定;二是即使以后网页端迭代、迁移服务器,iPhone 和 Mac 上的使用方式也无需改变。 ## 从一次选型讨论开始 这个项目最初并不是从“我要写一个日历网站”开始的,而是一个更实际的问题:怎样同时满足大学课表导入、日常日程、跨 iOS/macOS/Android 同步、提醒,以及未来由 AI 协助回顾一周工作? 最开始考虑过两类方案: | 方向 | 优点 | 局限 | | -------------------------------------------- | ------------------------------------------ | -------------------------------- | | Google Calendar / TickTick / Notion Calendar | 开箱即用,多平台成熟 | 数据与自动化边界受第三方平台约束 | | 自建 CalDAV 服务 | 数据归属清晰、系统日历原生接入、长期可扩展 | 需要自行完成部署、账户与网页管理 | 最终选择了第二条路。原因并不是“自建更酷”,而是 CalDAV 恰好把需求拆成了稳定且可维护的层次:日历同步交给成熟协议,网页只补足管理体验,AI 访问则通过独立的授权层实现。 在服务端软件的选择上,也考虑过 Nextcloud 这一类功能全面的平台。但在一台资源有限的个人服务器上,完整的应用套件意味着更高的内存与维护成本。因此当前版本采用更轻的 Radicale;如果未来服务规模或需求增长,仍可在不改变客户端连接方式的前提下迁移。 ## 简明实现路径 整套服务运行在 Docker Compose 中,结构保持轻量: ```text Internet │ ▼ calendar.hdaniel.studio │ HTTPS ▼ Nginx(反向代理) ├── /dav/ → Radicale(CalDAV 数据与同步) └── / → Daniel Calendar Portal(网页、账户、API) ``` 其中,Radicale 是轻量级的 CalDAV 服务,负责标准日历协议、日程文件和多端同步;Portal 是独立的网页层,负责将较复杂的 CalDAV 操作包装成更友好的界面和 API。 部署过程可以概括为四步: 1. 通过 Docker Compose 启动 Radicale 与 Portal。 2. 在反向代理中将 `/dav/` 转给 CalDAV 服务,其余页面交给 Portal。 3. 为域名配置 HTTPS,使系统日历客户端能够安全连接。 4. 在手机或电脑中添加 CalDAV 账户,之后所有设备自动同步同一份数据。 这套划分也为未来迁移留下余地:只要继续提供 CalDAV,底层存储或网页实现都可以替换,而用户的设备配置不用推倒重来。 ## 一次实际搭建中的关键问题 从“协议可以用”到“产品真的可用”,中间仍有许多容易被忽略的细节。以下是这次实现中最重要的几个经验: 1. **反向代理路径必须一致。** Portal、CalDAV 与公开说明页共用同一个域名,`/dav/` 需要稳定地交给 Radicale,网页和 API 则由 Portal 处理。 2. **不要重复定义 Nginx 的根路由。** 宝塔生成的反向代理配置已经包含通用 `/` 规则;新增功能应使用更具体的路径,避免产生重复 `location /`。 3. **iOS 与 macOS 的入口并不相同。** macOS 在“日历 → 添加账户”中配置,而 iPhone/iPad 是“设置 → 互联网账户 → 添加账户”。网页内因此分别给出分步引导。 4. **网页日程的查询不能漏掉重复事件。** 周视图需要正确展开课程的重复规则,并按本地时区显示;否则客户端正常、网页却会出现“少课”的错觉。 5. **令牌安全比便利更重要。** 完整 Token 只在创建时展示一次,服务端只保存摘要;令牌不应放进链接、日志或页面持久存储中。 ## 产品功能 | 模块 | 已实现能力 | | ---------- | ------------------------------------------------------------------------- | | 跨平台同步 | iPhone、iPad、macOS 原生日历,以及 Android 的 CalDAV 客户端同步同一份数据 | | 网页日历 | 按周查看 0:00–24:00 日程;支持前后翻周、颜色区分与完整时长展示 | | 日程管理 | 创建、编辑、删除日程;支持标题、开始结束时间、地点等信息 | | 日历偏好 | 新建、重命名、删除日历;为每个日历分配独立颜色 | | 课程与日常 | 可将课程表、工作、出行、项目和 Deadline 分到不同日历 | | ICS | 导入 ICS,或选择一个日历导出为一次性 ICS 文件 | | 多端配置 | 网页内提供 macOS、iPhone/iPad、Android 的分步连接指南 | | 账户安全 | 邀请码注册、独立账户密码、HTTPS 会话与令牌撤销 | | AI 访问 | 为用户自己的 Codex 创建只读或读写令牌,通过 API 查询和管理日程 | ## 日历管理:从“看日程”到“整理时间” 网页端的“日历管理”专注于阅读与编辑日程,而“设置 → 日历偏好”则专门处理日历本身: ```mermaid flowchart LR preferences["设置:日历偏好"] --> create["新建日历"] preferences --> rename["修改名称"] preferences --> color["分配颜色"] preferences --> remove["删除日历"] calendar_view["日历管理"] --> week["按周浏览"] calendar_view --> select_event["点击日程"] select_event --> edit_event["编辑或删除日程"] ``` 这种分工避免了一个页面同时承担过多操作:查看周安排时保持专注;需要维护分类时,再进入设置页面完成。 默认的新账户会自动拥有四个基础日历: - `Personal`:个人安排与生活事项; - `Courses`:课程表与学习安排; - `Projects`:项目推进与创作工作; - `Deadlines`:作业、报名、提交等截止日期。 它们不是强制分类,而是一个可以直接开始使用的起点。用户也可以新增“旅行”“社团”“健身”等日历,并根据偏好设置颜色。 ## ICS 与 CalDAV:两种不同的分享方式 Daniel Calendar 同时提供 ICS 导入导出与 CalDAV 同步,但它们解决的是不同问题。 | 方式 | 适合场景 | 是否实时同步 | | -------- | -------------------------------------------- | ------------ | | CalDAV | 自己的手机、电脑及长期使用的日历应用 | 是 | | ICS 导出 | 归档、一次性分享、转移到不支持 CalDAV 的工具 | 否 | ICS 文件是一个某一时刻的日历快照。导出之后,即使原日历继续更新,已经下载的 ICS 文件也不会自动变化;因此,多端日常使用仍应优先选择 CalDAV。 ## 让 AI 参与,但不让 AI 接管日历 AI 功能是 Daniel Calendar 的延伸,而不是日历的前提条件。即使完全不使用 Codex 或其他 AI,CalDAV 同步、网页管理和 ICS 导入导出都可以独立工作。 当用户希望让 AI 协助时,可以在“设置 → 外部访问”创建令牌,并选择权限: - **只读令牌**:适合查询今天安排、统计本周课程、寻找空闲时间。 - **读写令牌**:适合用自然语言创建日程、修改安排或建立新的日历。 ```mermaid sequenceDiagram participant U as 用户 participant C as Codex participant P as Daniel Calendar API participant D as CalDAV 日历 U->>C: “明天 14:00 加一个项目讨论” C->>P: 使用读写令牌创建日程 P->>D: 写入 CalDAV 日历 D-->>P: 保存成功 P-->>C: 返回新日程 C-->>U: 确认安排 D-->>U: 同步至手机与电脑日历 ``` 令牌只在创建时显示一次,之后服务端只保存不可逆摘要;不再需要时可以立即撤销。这样的设计让 AI 能够成为一个方便的“日历入口”,但仍受到用户明确授权和权限范围的约束。 为了降低首次配置门槛,服务还提供公开的 Codex 配置说明页: ```text https://calendar.hdaniel.studio/codex/ ``` 它只包含 API 使用规则、权限边界和首次只读连接流程,不包含任何用户 Token。用户创建自己的访问令牌后,只需把“配置说明链接 + 自己的 Token”交给新的 Codex 对话即可。这样既避免每个用户复制冗长提示词,也不会把凭据写进 URL。 这里有一个必须坚持的边界:**提示词决定 AI 应该如何工作,Token 才决定 AI 实际能做什么。** 即使提示词要求删除日程,只读令牌也必须被后端拒绝。  ## 产品特点 ### 1. 数据源属于自己 日程由自己的服务器保存,并通过公开的 CalDAV 标准提供访问,而不是被锁定在某一个商业应用中。 ### 2. 不牺牲原生体验 课程表和生活安排依然出现在 iPhone、Mac 的系统日历里;提醒、搜索、Siri 建议等体验仍然可以沿用熟悉的客户端。 ### 3. 网页端专注于缺失的能力 网页端提供原生日历客户端不太适合承担的功能:邀请码注册、日历分类与颜色、连接指南、ICS 文件管理和 AI 令牌管理。 ### 4. 协议优先,方便长期演进 CalDAV 是这里最重要的边界。将来无论更换网页框架、增加移动端,还是将服务迁移到性能更高的服务器,都不必改变客户端的基本连接方式。 ### 5. AI 是可选、受控的工具 AI 不拥有默认访问权。用户自主创建令牌、选择只读或读写权限,并且可以随时撤销授权。 ## 下一步 Daniel Calendar 目前已经具备作为个人日程中枢的基本能力。接下来可以继续探索的方向包括: - 基于日历的每周回顾:将课程、项目、日常安排与 AI 对话中的工作串联起来; - 更细致的空闲时间分析与 Deadline 提醒; - MCP Server 接入,让 AI 工具以更标准的方式访问日历; - 更完整的日历共享与订阅能力; - 更丰富的移动端配置诊断与同步状态提示。 但无论功能如何增加,最初的目标不会改变: > 让日程拥有一个稳定、开放、跨平台,并且真正属于自己的家。 最后修改:2026 年 09 月 06 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果愿意的话...或许可以请我喝杯奶茶。