【问题标题】:Have I found a bug in DateComponentsFormatter?我在 DateComponentsFormatter 中发现错误了吗?
【发布时间】:2020-12-05 18:18:33
【问题描述】:

在回答this question关于如何基于比较两个日期创建“xxx 前”字符串时,我写了一个完整的问题解决方案。

它涉及使用DateComponentsFormatter,其中maximumUnitCount 设置为1,unitsStyle 设置为.full。这是创建DateComponentsFormatter的代码:

 var timeFormatter:DateComponentsFormatter = {
    let temp = DateComponentsFormatter()
    temp.allowedUnits = [.year, .month, .weekOfMonth, .day, .hour, .minute, .second]
    temp.maximumUnitCount = 1
    temp.unitsStyle = .full
    return temp
}()

然后我写了一个函数,使用 DateComponentsFormatter 来输出“xxx units ago”字符串:

//Use our DateComponentsFormatter to generate a string showing "n <units> ago" where units is the largest units of the difference
//Between the now date and the specified date in te past
func timefromDateToNow(_ pastDate: Date) -> String {
    if let output = timeFormatter.string(from: pastDate, to: now) {
        return output + " ago"
    } else {
        return "error"
    }
}

我用这样的代码计算过去的日期:

let value = Double.random(in: min ... max)
let past = now.addingTimeInterval(value)

奇怪的是,对于value 的某些值,我得到的字符串是“0 个月前”。我能够捕获的值是-408754.0,大约是 4 天 17 小时。

为什么调用timeFormatter.string(from: Date(timeIntervalSinceNow: -408754.0), to: Date()) 会返回一个0 个月的字符串?它应该显示“4 天”的结果!

【问题讨论】:

  • 即使没有读过这篇文章,我也可以告诉你,DateComponentsFormatter 多年来对我产生了不一致、奇怪,有时甚至是错误的结果(即当限制为 1 时返回多个组件)。阅读这篇文章后,我也经历了这种确切的行为。
  • @bsod 您是否针对任何此类行为提交了错误报告?
  • 不,不幸的是我没有,我是一个糟糕的开发人员
  • @DuncanC 现在你明白我为什么说 DCF 有问题了。
  • 一个简单的解决方法是使用两个日期之间的时间间隔timeFormatter.string(from: Date().timeIntervalSince(pastDate))

标签: ios swift nsdatecomponentsformatter


【解决方案1】:

如果您想参考多久以前,请考虑RelativeDateTimeFormatter,例如

let formatter = RelativeDateTimeFormatter()
formatter.dateTimeStyle = .named
formatter.unitsStyle = .spellOut
formatter.formattingContext = .beginningOfSentence

let date = Date()

let longTimeAgo = date.addingTimeInterval(-10_000_000)
print(formatter.localizedString(for: longTimeAgo, relativeTo: date)) // Three months ago

let veryLongTimeAgo = date.addingTimeInterval(-100_000_000)
print(formatter.localizedString(for: veryLongTimeAgo, relativeTo: date)) // Three years ago

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-01
    • 2021-04-06
    • 1970-01-01
    • 2014-09-12
    • 1970-01-01
    • 2012-08-20
    • 2011-02-11
    • 2021-11-27
    相关资源
    最近更新 更多