检查两个日期之间是否在 iOS16.3 下不再有效

Check if between two dates is no longer working under iOS16.3

提问人:iKK 提问时间:2/4/2023 最后编辑:iKK 更新时间:2/4/2023 访问量:54

问:

使用 iOS16.3、XCode14.2、Swift5.7.2、

为什么以下方法不再有效?

我通过设置和以及...date = Date()maximumDate = Date()

根据这个解决方案,它应该有效 - 但它没有

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

它应该回来!为什么它返回 false ???true

顺便说一句,如果和date = Date()maximumDate = Date().addingTimeInterval(1)

很奇怪,不是吗?

swift date swiftui 日期比较

评论

1赞 Michael Hulet 2/4/2023
看起来您正在测试的日期与此字符串表示形式中的上限完全相同。有没有可能它实际上是在上限之后的几分之一秒? (因此)精确到不到一毫秒,因此这种字符串格式会失去一些精度TimeIntervalDate
0赞 iKK 2/4/2023
好主意,谢谢。事实一定是这样。看来时机在这里起着重要作用......

答:

1赞 Duncan C 2/4/2023 #1

没有必要如此复杂。日期对象符合 和 协议,因此测试介于 2 个其他日期之间的日期是一行:ComparableEquatable

extension Date {
    func between(start: Date, end: Date) -> Bool {
       return self > start && self < end
    }
}

你可以这样使用它:

let date = Date()

if date.betweeen(start: someDate, end: someOtherDate) {
    // the date is between the start and the end
} else {
    // The date is not between the start and end dates
}

仅当相关日期不等于开始日期或结束日期时,上述内容才会返回 true。您可以通过在比较中使用 和 而不是 和 轻松更改它以匹配与开始日期和结束日期匹配的日期。>=<=><

正如评论中所讨论的,Date 对象具有亚毫秒级精度。两个看起来相同的日期可能相差几分之一秒,验证比较的最佳方法是将日期转换为十进制秒并记录秒值。(请参阅属性。DatetimeIntervalSinceReferenceDate

编辑:

使用上述示例查看此示例代码:

extension Date {
    func between(start: Date, end: Date) -> Bool {
       return self > start && self < end
    }
    var asStringWithDecimal: String {
        return DateFormatter.localizedString(from: self, dateStyle: .medium, timeStyle: .medium) + " ( \(self.timeIntervalSinceReferenceDate) seconds)"
    }
}
let now = Date()

for _ in (1...5) {
    let random = Double.random(in: -1.5...1.5)
    let test = now.advanced(by: random)
    let start = now.advanced(by: -1)
    let end = now.advanced(by: 1)

    let isBetween = test.between(start: start, end: end)
    let isOrNot = isBetween ? "is" : "is not"

    let output = "\(test.asStringWithDecimal) \n  \(isOrNot) between \n    \(start.asStringWithDecimal) and \n    \(end.asStringWithDecimal)"
    print(output)
}

这将在当前日期的 1.5 秒±生成 5 个随机日期,然后测试每个日期以查看它是否在当前日期的 1 秒内。它将结果记录为日期字符串和双精度,因此您可以看到秒数匹配时发生的情况(但秒的分数可能不匹配)。

评论

0赞 iKK 2/4/2023
非常感谢邓肯 - 非常好的解决方案。真正欺骗我的是,我的maximumDate=Date()比date=Date()早了几分之一秒 - 这使得两者不同!日志没有考虑到这一点。
0赞 Duncan C 2/4/2023
请参阅对我的答案的编辑。我添加了一些测试代码,将日期记录为日期字符串双精度,以便您可以查看非常接近开始或结束日期的日期发生了什么。
0赞 Duncan C 2/4/2023
如果您想知道您的日期是否介于其他两个日期与第二个日期之间,可以截断日期的 timeIntervalSinceReferenceDate 值并进行比较。如果要与其他精度(如分钟、小时或天)进行比较,可以使用 日历 函数 .这将使您判断您的日期是否在相同的秒、分钟、小时、日、周或您想要的任何时间。Datecompare(_:to:toGranularity:)