I'm not sure what I'm doing wrong here. If you run this code in a Xcode Playground (I'm using 11.1) you will see it failing for random dates that, in my system, happen to be somewhere after 6500 days added to the current date. However those dates aren't fixed.
(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!)")
}
}
Some output (failed from 130 to 160 times in my tests, output vary):
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]
That is due to rounding errors (note that a Date
is internally represented as a floating point number holding the number of seconds since January 1, 2001). If you retrieve more components of the difference
let difference = calendar.dateComponents([.day, .hour, .minute, .second, .nanosecond],
from: date, to: someFutureDate)
then you'll notice that it is in the first example something like
day: 6656 hour: 23 minute: 59 second: 59 nanosecond: 999999755
which is almost the expected 6657 days. A possible fix seems to be to remove the “fractional part” of the date with
let date = calendar.date(bySetting: .nanosecond, value: 0, of: Date())!
or
let date = Date(timeIntervalSinceReferenceDate:
Date().timeIntervalSinceReferenceDate.rounded())
With this change, I could not observe a difference anymore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With