RelativeDateTimeFormatter输出结果比预期少一天:为何下述代码打印"Tomorrow"而非"In 2 days"?
RelativeDateTimeFormatter 返回"Tomorrow"而非"In 2 days"的原因与解决办法
这问题的核心在于时区转换和日期组件计算的细节,咱们一步步拆解:
问题根源分析
从你的控制台日志能看到关键信息:
- 解析后的
date是2022-05-20 22:00:00 +0000,而非你预期的2022-05-21 00:00:00 +0000 - 当前时间
now是2022-05-19 15:44:00 +0000
为什么date会少2小时?因为DateFormatter默认使用当前设备的本地时区。假设你所在时区是UTC+2,那么本地时间的2022-05-21转换成UTC时间就是2022-05-20 22:00:00。
接下来计算时间差时,Calendar.current.dateComponents([.year, .month, .day], from: now, to: date)只统计完整的天数差:从2022-05-19 15:44 UTC到2022-05-20 22:00 UTC,间隔是1天6小时16分钟,完整天数只有1天,所以RelativeDateTimeFormatter会输出"Tomorrow",而非你预期的"In 2 days"。
解决办法
要让计算符合你的预期,需要确保解析后的日期是当天的起始时间(00:00),并且基于统一时区计算。这里有两种可靠的方式:
方法1:设置DateFormatter的时区为UTC(或你期望的时区)
强制DateFormatter用UTC解析日期,保证解析结果是当天的0点:
let dateString = "2022-05-21" let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" dateFormatter.timeZone = TimeZone(identifier: "UTC") // 指定时区 let date = dateFormatter.date(from: dateString)!
方法2:将解析后的日期调整为本地时区的当天起始时间
如果需要基于本地时区计算,用Calendar把日期重置到当天开始:
let dateString = "2022-05-21" let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let date = dateFormatter.date(from: dateString)! let startOfDate = Calendar.current.startOfDay(for: date) // 获取当天起始时间
之后计算时间差时,用调整后的startOfDate结合当前时间的起始时间:
let startOfNow = Calendar.current.startOfDay(for: Date()) let dateComponents = Calendar.current.dateComponents([.year, .month, .day], from: startOfNow, to: startOfDate) print(relativeDateTimeFormatter.localizedString(from: dateComponents)) // 会输出"In 2 days"
这样就能保证计算的是两个日期完整天数的差值,完全符合你的预期。
内容的提问来源于stack exchange,提问作者Giorgio
相关产品推荐
相关产品推荐

