I am using the built in DateComponentsFormatter to figure out the number of years between the current day and another date. If the date gets too far in the past for example 1940, the returned units are wrong:
let dateComponents = DateComponents(year: 1940, month: 1, day: 2, hour: 1, minute: 1, second: 1)
let date = Calendar.current.date(from: dateComponents)!
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [.year]
dateComponentsFormatter.unitsStyle = .full
print(dateComponentsFormatter.string(from: abs(date.timeIntervalSinceNow)))
This prints -58 years
which is incorrect. Is this an Apple bug? Am I doing something wrong?
It is a bug in DateComponentsFormatter
's implementation.
They apparently are using Int32 internally to represent time intervals.
I ran into the same issue, it's very easy to reproduce:
let interval: TimeInterval = ... some number here
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.second]
formatter.unitsStyle = .abbreviated
print(formatter.string(from: interval) ?? "")
This is supposed to output just the number of seconds, without any special calculations. Even that only works as expected up until 2147483647 (which happens to be Int32.max). Everything over that simply overflows and produces incorrect results.
This maximum "supported" number of seconds is 68y 2w 4d 3h 14m 7s, which explains why you are seeing it also.
UPD
Someone already filed a radar: http://www.openradar.me/32513237 and mentioned a workaround there, and it works!
In your case that would be instead using:
let date = Calendar.current.date(from: dateComponents)!
let now = Date()
dateComponentsFormatter.string(from: date, to: now)