Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift dates are equivalent under 30 nanoseconds

I noticed that when comparing two instances of a Swift Date with ==, they qualify as the same date when the difference in DateComponents.nanoseconds is less than 30. For example:

let calendar = Calendar(identifier: .gregorian)
let startComps = DateComponents(year: 2017, month: 1, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0)
let endComps = DateComponents(year: 2017, month: 1, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 29)

let startDate = calendar.date(from: startComps)!
let endDate = calendar.date(from: endComps)!
print(startDate == endDate)
//prints true, changing 29 to 30 prints false

The behavior is the same if comparing with startDate.compare(endDate) == .orderedSame. I couldn't find any mention of this in the docs or headers. Is there a logical reason for 30 nanoseconds to be the cutoff for equality?

like image 664
blwinters Avatar asked Sep 11 '17 18:09

blwinters


1 Answers

Dates are represented internally as a Double. Doubles have a limited precision. Your first date there has an internal value of 504950400.000000000000000 (when printed at 15 decimal places). The next higher representable value is 504950400.000000059604645. It just so happens that your end date, if you set the nanoseconds to 30, is 504950400.000000059604645 (which actually corresponds to a nanoseconds value of 59).

Which is to say, in January of 2017, Date can only distinguish between 59-nanosecond intervals. Meanwhile back in January of 2001, Date can distinguish every single nanosecond. And in 2027 it will distinguish between 119-nanosecond intervals.

like image 65
Lily Ballard Avatar answered Sep 19 '22 02:09

Lily Ballard