在日期中加上天数,计算出差异不会导致预期结果

And*_*dré 5 date gregorian-calendar swift

我不确定我在做什么错。如果您在Xcode Playground(我使用的是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!)")
    }
}
Run Code Online (Sandbox Code Playgroud)

一些输出(在我的测试中从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]
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 4

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

\n\n
let difference = calendar.dateComponents([.day, .hour, .minute, .second, .nanosecond],\n                                         from: date, to: someFutureDate)\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后你会注意到第一个例子是这样的

\n\n
day: 6656 hour: 23 minute: 59 second: 59 nanosecond: 999999755 \n
Run Code Online (Sandbox Code Playgroud)\n\n

几乎是预期的 6657 天。一个可能的修复似乎是删除日期的 \xe2\x80\x9cfractional 部分\xe2\x80\x9d

\n\n
let date = calendar.date(bySetting: .nanosecond, value: 0, of: Date())!\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者

\n\n
let date = Date(timeIntervalSinceReferenceDate:\n                Date().timeIntervalSinceReferenceDate.rounded())\n
Run Code Online (Sandbox Code Playgroud)\n\n

有了这个变化,我就无法再观察到差异了。

\n