DateComponentsFormatter 不适用于过去的日期

Posted

技术标签:

【中文标题】DateComponentsFormatter 不适用于过去的日期【英文标题】:DateComponentsFormatter not working with dates far in the past 【发布时间】:2017-07-15 14:51:49 【问题描述】:

我正在使用内置的 DateComponentsFormatter 来计算当前日期和另一个日期之间的年数。如果日期过早,例如 1940,则返回的单位是错误的:

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)))

这会打印出不正确的-58 years。这是苹果的错误吗?我做错了吗?

【问题讨论】:

print(dateComponentsFormatter.string(from: date, to: Date()) ?? "") @LeoDabus 谢谢我也尝试过更好的方法,但并不总是提供相同的价值......有时是 70 年,有时是 69 年 它给了我 77 年 您可能遇到了时代问题? @Stephen 每次使用 2088 时都会给我“-70 年\n”。顺便说一句,添加时代组件不会有所作为 【参考方案1】:

这是DateComponentsFormatter 的实现中的一个错误。 他们显然在内部使用 Int32 来表示时间间隔。

我遇到了同样的问题,很容易重现:

let interval: TimeInterval = ... some number here
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.second]
formatter.unitsStyle = .abbreviated
print(formatter.string(from: interval) ?? "")

这应该只输出秒数,没有任何特殊计算。 即使这样也只能按预期工作,直到 2147483647(恰好是 Int32.max)。超出此范围的所有内容都会溢出并产生不正确的结果。

这个“支持”的最大秒数是 68y 2w 4d 3h 14m 7s,这就解释了为什么你也会看到它。

UPD

有人已经提交了雷达:http://www.openradar.me/32513237 并在那里提到了一种解决方法,并且它有效!

在您的情况下,将改为使用:

let date = Calendar.current.date(from: dateComponents)!
let now = Date()
dateComponentsFormatter.string(from: date, to: now)

【讨论】:

以上是关于DateComponentsFormatter 不适用于过去的日期的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 DateComponentsFormatter 在 HH:MM 中格式化从 00:00 开始的时间间隔偏移量

时光不老我们不散啥意思 怎么理解时光不老我们不散的意思

时光不老我们不散这句话是啥意思 时光不老我们不散这句话解释

C语言 不允许使用不完整的类型

时光不老,我们不散的下一句是啥?

C语言 不允许使用不完整的类型