iOS16.3下Swift日期区间判断方法失效问题排查
iOS16.3/Xcode14.2/Swift5.7.2下日期区间判断失效问题
问题场景
在iOS16.3、Xcode14.2、Swift5.7.2环境中,调用日期区间判断方法时,设置date = Date()且maximumDate = Date(),预期返回true但实际返回false;仅当设置maximumDate = Date().addingTimeInterval(1)时,方法才正常工作。
相关代码
public class THManager : ObservableObject { @Published public var minimumDate: Date = Date() @Published public var maximumDate: Date = Date() public func isBetweenMinAndMaxDates(date: Date) -> Bool { print(min(minimumDate, maximumDate)) print(max(minimumDate, maximumDate)) print(min(minimumDate, maximumDate)...max(minimumDate, maximumDate)) print(date) print((min(minimumDate, maximumDate)...max(minimumDate, maximumDate)).contains(date)) return (min(minimumDate, maximumDate)...max(minimumDate, maximumDate)).contains(date) } }
打印结果
2022-02-08 19:45:51 +0000 2023-02-03 19:45:51 +0000 2022-02-08 19:45:51 +0000...2023-02-03 19:45:51 +0000 2023-02-03 19:45:51 +0000 false
原因分析与解决方案
原因
问题核心在于Date的高精度特性和闭区间的判断逻辑:
- Date类型精度达到纳秒级,你创建的
minimumDate、maximumDate和传入的date虽然打印显示时间相同,但实际创建有先后顺序,纳秒级数值存在微小差异。 - 当
maximumDate的实际纳秒值略小于传入的date时,闭区间...的contains方法会判定date超出范围,返回false;给maximumDate加1秒后,其数值必然大于date,判断自然正常。
解决方案
方案一:统一精度后比较
将所有日期转换为秒级时间戳,消除纳秒差异:
public func isBetweenMinAndMaxDates(date: Date) -> Bool { let minTimestamp = min(minimumDate.timeIntervalSince1970, maximumDate.timeIntervalSince1970) let maxTimestamp = max(minimumDate.timeIntervalSince1970, maximumDate.timeIntervalSince1970) let dateTimestamp = date.timeIntervalSince1970 return dateTimestamp >= minTimestamp && dateTimestamp <= maxTimestamp }
方案二:直接使用上下限比较
替代区间判断逻辑,直接进行日期大小比较,更直观且避免精度问题:
public func isBetweenMinAndMaxDates(date: Date) -> Bool { let lowerBound = min(minimumDate, maximumDate) let upperBound = max(minimumDate, maximumDate) return date >= lowerBound && date <= upperBound }
内容的提问来源于stack exchange,提问作者iKK
相关产品推荐
相关产品推荐

