iOS Calendar在太平洋标准时区下添加事件日期错误问题
问题根因
- 代码存在大量无意义的
Date与字符串来回转换逻辑,Date本质是不带时区属性的UTC时间戳,反复转字符串再转Date的操作会额外引入时区计算误差。 - 太平洋时区(PT)比UTC晚8小时(夏令时期间晚7小时),当原始活动时间对应的UTC时间转换为太平洋时区时,就可能落到前一天,你手动处理时区的逻辑错误放大了这个偏移。
- 代码中计算得到的活动实际时间
newStartDate完全没有被使用,反而把当前系统时间date作为了事件的开始时间,属于核心逻辑错误。
修复方案
EKEvent的startDate和endDate本身接收的是绝对UTC时间戳,系统日历会自动根据用户当前时区调整显示的当地时间,不需要你手动做任何时区转换:
// 直接使用活动原始的startDate即可,无需额外转换 calendarEvent.location = eventLocation calendarEvent.startDate = session.startDate calendarEvent.endDate = session.startDate.addingTimeInterval(Double(session.duration) * 60.0)
如果你的session.startDate是从特定时区的字符串解析得到的,只需要在第一次解析的时候指定对应时区即可,解析得到Date后不需要再做任何处理,示例如下:
// 仅当session.startDate是字符串类型时需要做解析,以下示例假设原始字符串对应东八区时间 let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MM/dd/yyyy, hh:mm:ss a" // 优先用时区标识符而非缩写,避免歧义 dateFormatter.timeZone = TimeZone(identifier: "Asia/Shanghai") guard let startDate = dateFormatter.date(from: session.startDateStr) else { // 自行添加解析失败的处理逻辑 return } calendarEvent.location = eventLocation calendarEvent.startDate = startDate calendarEvent.endDate = startDate.addingTimeInterval(Double(session.duration) * 60.0)
注意事项
- 不要使用时区缩写(比如UTC、PT)创建
TimeZone,部分缩写在不同地区存在歧义,优先使用时区标识符比如UTC、America/Los_Angeles、Asia/Shanghai。 - 不要做无意义的
Date转字符串再转回Date的操作,只会额外引入误差。
内容的提问来源于stack exchange,提问作者Mkaur
相关产品推荐
相关产品推荐

