为何Date()与Calendar.current.startOfDay(for: Date())返回日期不一致?
问题描述
我需要存储用户操作的Date数据,无论用户何时执行操作,都将其设置为当日起始时间(即用户执行30种不同操作,均存储为同一Date)。但目前出现异常:撰写时为6月29日,调用Calendar.startOfDay却返回6月28日的时间:
print(Date()) print(Calendar.current.startOfDay(for: Date())) // 输出结果: // 2024-06-29 14:30:18 +0000 // 2024-06-28 21:00:00 +0000
后续尝试了另一种构造当日起始时间的方法,结果仍为6月28日:
let calendar = Calendar.current var components = calendar.dateComponents([.year, .month, .day], from: date) components.hour = 0 components.minute = 0 components.second = 0 return calendar.date(from: components) ?? .now
请问如何确保日期一致?
解决方案
出现这个问题的核心原因是时区差异:
Date本质是UTC时间戳,打印时显示的是UTC时区的时间Calendar.current使用设备本地时区(比如UTC-5时区),本地时区的当日0点转换为UTC时间就是前一天的21点(6月29日0点 UTC-5 = 6月28日21点 UTC)
根据业务需求,分两种场景处理:
场景1:基于本地时区存储当日起始时间
如果业务逻辑以用户本地时区的“当日”为准,当前代码逻辑是正确的——只是UTC格式的打印结果看起来是前一天,实际对应本地时区的6月29日0点。可通过转换为本地时区字符串验证:
let dateFormatter = DateFormatter() dateFormatter.timeZone = TimeZone.current dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z" let now = Date() let startOfDay = Calendar.current.startOfDay(for: now) print(dateFormatter.string(from: now)) // 本地时区当前时间,例:2024-06-29 10:30:18 -0400 print(dateFormatter.string(from: startOfDay)) // 本地时区当日0点,例:2024-06-29 00:00:00 -0400
场景2:统一基于UTC时区存储当日起始时间
如果需要所有用户统一使用UTC时区的“当日”,需创建指定UTC时区的Calendar实例:
// 创建UTC时区的日历 var utcCalendar = Calendar.current utcCalendar.timeZone = TimeZone(identifier: "UTC")! // 获取UTC时区的当日起始时间 let utcStartOfDay = utcCalendar.startOfDay(for: Date()) print(utcStartOfDay) // 输出:2024-06-29 00:00:00 +0000
也可通过日期组件实现:
var utcCalendar = Calendar.current utcCalendar.timeZone = TimeZone(identifier: "UTC")! var components = utcCalendar.dateComponents([.year, .month, .day], from: Date()) components.hour = 0 components.minute = 0 components.second = 0 let utcStartOfDay = utcCalendar.date(from: components) ?? .now print(utcStartOfDay) // 输出:2024-06-29 00:00:00 +0000
内容的提问来源于stack exchange,提问作者Ilja
相关产品推荐
相关产品推荐

