将日期添加到日期并计算差异不会导致预期结果

Add days to a date and computing the difference doesn't lead to expected result

我不确定我做错了什么。如果您 运行 在 Xcode 游乐场(我使用的是 11.1)中使用此代码,您会看到随机日期失败,在我的系统中,该日期恰好在添加到当前日期 6500 天之后. 但是这些日期不是固定的。

(1...10000).forEach { days in
    let calendar = Calendar(identifier: .gregorian)
    var dayComponent = DateComponents()
    dayComponent.day = days
    let date = Date()
    let someFutureDate = calendar.date(byAdding: dayComponent, to: date)!

    let difference = calendar.dateComponents([.day], from: date, to: someFutureDate)

    if (days != difference.day!) {
        print("WAT \(date) - \(someFutureDate) \(days) \(difference.day!)")
    }
}

一些输出(在我的测试中失败了 130 到 160 次,输出变化):

WAT 2019-10-31 14:01:47 +0000 - 2038-01-21 14:01:47 +0000 6657 6656
WAT 2019-10-31 14:01:47 +0000 - 2038-01-26 14:01:47 +0000 6662 6661
WAT 2019-10-31 14:01:47 +0000 - 2038-02-02 14:01:47 +0000 6669 6668
WAT 2019-10-31 14:01:47 +0000 - 2038-02-05 14:01:47 +0000 6672 6671
WAT 2019-10-31 14:01:47 +0000 - 2038-02-12 14:01:47 +0000 6679 6678
WAT 2019-10-31 14:01:47 +0000 - 2038-02-14 14:01:47 +0000 6681 6680
[snip]

这是由于舍入误差造成的(请注意,Date 在内部表示为一个浮点数,表示自 2001 年 1 月 1 日以来的秒数)。如果你检索更多的组件差异

let difference = calendar.dateComponents([.day, .hour, .minute, .second, .nanosecond],
                                         from: date, to: someFutureDate)

然后你会注意到它在第一个示例中类似于

day: 6656 hour: 23 minute: 59 second: 59 nanosecond: 999999755 

几乎 预期的 6657 天。一个可能的解决方法似乎是用

删除日期的“小数部分”
let date = calendar.date(bySetting: .nanosecond, value: 0, of: Date())!

let date = Date(timeIntervalSinceReferenceDate:
                Date().timeIntervalSinceReferenceDate.rounded())

有了这个变化,我再也看不出有什么不同了。