踩坑速览(重要的说在前头)
本以为“只要接个接口、跑个脚本、连个日历”,没想到问题重重…
主要遇到了两个问题
-
Apple ID 必须是邮箱注册的
要用 CalDAV 连接 iCloud,必须拥有一个 iCloud 邮箱地址(@icloud.com)。
👉 解决办法:重新注册一个带 iCloud 邮箱的 Apple ID。 -
CalDAV 无法通过验证
按照常规步骤,进入 设置 → 日历 → 账户 添加 CalDAV,但输入正确信息后,始终无法通过验证。尝试多次后只好作罢。注意:需要在iCloud官网中添加一个App专用密码,路径在:右上角的图标-管理Apple账户。
代码
# 测试连接情况
from caldav import DAVClient
client = DAVClient(
url="https://caldav.icloud.com/",
username="xxxx@icloud.com",
password="APP专用密码",
ssl_verify_cert=False
)
principal = client.principal()
print("✅ 连接成功!")
# main.py
from datetime import datetime, timedelta
import requests
from schedule_builder import build_schedule
from calendar_helper import write_schedule_to_icloud
APPLE_ID = "替换为你的 Apple ID"
APP_SPECIFIC_PASSWORD = "替换为你的 App 专用密码"
CALENDAR_NAME = "日历名称" # 要在日历App-日历(导航栏中间)中新建一个对应名字的
tomorrow = datetime.now() + timedelta(days=1)
tomorrow_str = tomorrow.strftime('%Y-%m-%d')
weekday = tomorrow.weekday()
url = f"https://timor.tech/api/holiday/info/{tomorrow_str}"
response = requests.get(url)
is_holiday = False
if response.ok:
data = response.json()
is_holiday = data.get("holiday", {}).get("holiday", False) or data.get("type", {}).get("type") == 1
schedule = build_schedule(date=tomorrow, weekday=weekday, is_holiday=is_holiday)
write_schedule_to_icloud(schedule, APPLE_ID, APP_SPECIFIC_PASSWORD, CALENDAR_NAME)
print(f"✅ 明天({tomorrow_str})的日程已写入日历:{CALENDAR_NAME}")
# calendar_helper.py
from caldav import DAVClient
from caldav.elements import dav, cdav
from datetime import datetime
from caldav.lib.error import AuthorizationError
import os
def write_schedule_to_icloud(events, apple_id, app_password, calendar_name):
url = 'https://caldav.icloud.com.cn/'
client = DAVClient(url, username=apple_id, password=app_password)
principal = client.principal()
calendars = principal.calendars()
calendar = None
for cal in calendars:
if calendar_name in cal.name:
calendar = cal
break
if calendar is None:
raise ValueError(f"未找到日历:{calendar_name}")
for event in events:
dtstamp = datetime.now().strftime('%Y%m%dT%H%M%S')
uid = f"elite-plan-{event['dtstart']}-{event['summary'].replace(' ', '')}"
ical = f"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//ElitePlan//EN
BEGIN:VEVENT
UID:{uid}
DTSTAMP:{dtstamp}Z
DTSTART;TZID=Asia/Shanghai:{event['dtstart']}
DTEND;TZID=Asia/Shanghai:{event['dtend']}
SUMMARY:{event['summary']}
END:VEVENT
END:VCALENDAR
"""
try:
calendar.add_event(ical)
except AuthorizationError as e:
print(f"⚠️ 无法写入 iCloud,已降级为本地导出 .ics:{uid}.ics")
with open(f"{uid}.ics", "w", encoding="utf-8") as f:
f.write(ical)
# schedule_builder.py
from datetime import datetime, timedelta
def build_schedule(date: datetime, weekday: int, is_holiday: bool):
events = []
date_str = date.strftime('%Y%m%d')
def add_event(summary, start_time, end_time):
dt_start = f"{date_str}T{start_time}00"
dt_end = f"{date_str}T{end_time}00"
events.append({
"summary": summary,
"dtstart": dt_start,
"dtend": dt_end
})
is_weekend = weekday >= 5
if not is_holiday and not is_weekend:
if weekday in [1, 3, 5]:
add_event("英语阅读", "060000", "071000")
elif weekday in [2, 4, 6]:
add_event("跑步锻炼", "060000", "071000")
add_event("规划时间(晚上)", "200000", "213000")
add_event("阅读时间", "213000", "221500")
add_event("准备入睡", "221500", "223000")
else:
if weekday in [1, 3, 5, 6]:
add_event("英语阅读", "060000", "071000")
elif weekday in [2, 4]:
add_event("跑步锻炼", "060000", "071000")
add_event("洗澡准备", "071000", "080000")
add_event("规划时间(上午1)", "080000", "093000")
add_event("休息", "093000", "094000")
add_event("规划时间(上午2)", "094000", "113000")
add_event("午间休息", "113000", "133000")
add_event("苏醒时间", "133000", "140000")
add_event("规划时间(下午1)", "140000", "153000")
add_event("下午茶时间", "153000", "160000")
add_event("规划时间(下午2)", "160000", "173000")
add_event("晚间休息", "173000", "200000")
add_event("规划时间(晚上)", "200000", "213000")
add_event("阅读时间", "213000", "221500")
add_event("准备入睡", "221500", "223000")
return events
2869

被折叠的 条评论
为什么被折叠?



