如何判断日期是否距次日零点仅差1秒?现有代码返回错误结果
问题
需要检查输入的日期是否距离次日零点仅差1秒(日期格式:"2023-05-20T23:59:59.000+05:30"),编写了如下Date扩展代码,但测试目标日期时预期输出true,实际返回false,请指出错误:
extension Date { var isOneSecondAway: Bool { let calendar = Calendar.current let nextStartOfDay = calendar.date(byAdding: .day, value: 1, to: self.startOfDay) ?? self let timeIntervalInSeconds = Int(nextStartOfDay.startOfDay.timeIntervalSince(self)) return timeIntervalInSeconds == 1 } var startOfDay: Date { return Calendar.current.startOfDay(for: self) } } let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" let targetDateString = "2023-05-20T23:59:59.000+05:30" guard let targetDate = dateFormatter.date(from: targetDateString) else {return} print(targetDate.isOneSecondAway)
错误原因与修复
核心错误点
- 重复调用
startOfDay:你已经通过calendar.date(byAdding: .day, value: 1, to: self.startOfDay)得到了次日的零点时间,却额外调用了nextStartOfDay.startOfDay——这完全是冗余操作,实际计算的是次日零点的当天零点(也就是当前日期加2天的零点)与目标日期的间隔,结果是86400秒,自然返回false。 - 精度处理缺失:直接将浮点型的时间间隔转成
Int,可能丢失毫秒级精度,极端场景下会导致判断失效。
修正后的代码
extension Date { var isOneSecondAwayFromNextMidnight: Bool { let calendar = Calendar.current guard let nextMidnight = calendar.date(byAdding: .day, value: 1, to: calendar.startOfDay(for: self)) else { return false } let interval = nextMidnight.timeIntervalSince(self) // 用近似判断避免浮点精度问题 return abs(interval - 1.0) < 0.001 } } let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" let targetDateString = "2023-05-20T23:59:59.000+05:30" guard let targetDate = dateFormatter.date(from: targetDateString) else { fatalError("日期解析失败") } print(targetDate.isOneSecondAwayFromNextMidnight) // 输出 true
额外优化说明
- 变量命名更明确:将
isOneSecondAway改为isOneSecondAwayFromNextMidnight,避免歧义。 - 增强容错性:用
guard let替代?? self,确保获取次日零点失败时返回明确的false,避免逻辑混乱。 - 处理浮点精度:
Date的时间间隔是浮点型,直接判断等于1可能因为毫秒误差失效,用近似范围判断更可靠。
内容的提问来源于stack exchange,提问作者iOSDev2013
相关产品推荐
相关产品推荐

