【问题标题】:Date/Time Natural Language Approximation in SwiftSwift 中的日期/时间自然语言逼近
【发布时间】:2015-07-28 20:15:54
【问题描述】:

我正在尝试使用 Swift 将 UTC 格式的日期从 API 转换为人类可读的近似格式。

我正在寻找类似以下的内容:

2015-07-14T13:51:05.423Z

大约两周前

在 Swift 中最好的方法是什么?虽然这可以直接格式化字符串,但我知道这可能需要将字符串转换为 NSDate 对象。

任何帮助将不胜感激。

编辑:我的问题已被确定为可能与 another question 重复。下面汤姆的解决方案是为 Swift 编写的,并且比针对我的情况创建一个新方法要优雅得多。

【问题讨论】:

标签: swift cocoa-touch datetime nsdateformatter swift2


【解决方案1】:

您需要两个步骤。首先,将您的日期字符串转换为NSDate

let dateString = "2015-07-14T13:51:05.423Z"

let df = NSDateFormatter()
df.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date = df.dateFromString(dateString)

(如果这不是您获得的字符串的精确表示,则必须更改日期格式字符串才能进行转换)。

接下来,使用NSDateComponentsFormatter 获取您想要的字符串:

let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyle.Full
formatter.includesApproximationPhrase = true
formatter.includesTimeRemainingPhrase = false
formatter.allowedUnits = NSCalendarUnit.WeekOfMonthCalendarUnit

if let pastDate = date {
    let dateRelativeString = formatter.stringFromDate(pastDate, toDate: NSDate())
}

今天是 7 月 28 日,因此该字符串的结果是“大约 2 周”。 allowedUnits 属性是一个位字段,因此您可以指定任意数量的单位类型。

【讨论】:

  • 感谢汤姆,解决方案效果很好!我做了一些修改以满足我的需要。首先,我将 allowedUnits 更改为 [.Year, .Month, .WeekOfMonth, .Day, .Hour, .Minute, .Second],然后添加了 formatter.maximumUnitCount = 1,这似乎产生了最好的“自然近似”结果。编辑:只是注意到我的 NSCalendarUnit 数组反映了 Swift 2 的使用情况
  • 如果您重复使用它(即在表格视图单元格上)应该注意的一点是,创建日期格式化程序会消耗一些 CPU,因此保留一个日期格式化程序会很方便被重复使用(例如,在 viewDidLoad 中创建它)。
  • 很高兴知道这与使用非常广泛的 FormatterKit 中的 TTTTimeIntervalFormatter 相比如何。
【解决方案2】:

正如 Tom Harrington 的回答所指出的,您可以使用 NSDateComponentsFormatter 生成一个时刻或时间间隔的口语表示。

但是,如果您想完全按照示例中的问题进行操作,即生成一个相对于当前时刻的过去时刻的口语表示,例如时间线面向的UI,那么NSDateComponentsFormatter 好像不合适。正如stringFromTimeInterval(_:) 的文档所说,时间间隔值“必须是有限数。创建字符串时,负数被视为正数。”

据我所知,最好的选择是 TTTTimeIntervalFormatter,这是 Mattt Thompson 的 FormatterKit 中的一个独立类。

我制作了一个 Xcode 7 Playground,RelativeDatePlayground,它将NSDateFormatter 的输出与TTTTimeIntervalFormatter 进行比较。这是一个表格,显示了不同相对时间的输出(以秒为单位)。如您所见,NSDateComponentsFormatter 似乎无法很好地处理过去或现在:

        -1488010 |               2 weeks ago |         -1 week remaining
        -1468800 |               2 weeks ago |         -1 week remaining
         -864000 |                1 week ago |       0 seconds remaining
          -86400 |                 1 day ago |          -1 day remaining
          -36000 |              10 hours ago |       -10 hours remaining
           -3600 |                1 hour ago |         -1 hour remaining
            -600 |            10 minutes ago |     -10 minutes remaining
             -60 |              1 minute ago |       -1 minute remaining
             -10 |            10 seconds ago |     -10 seconds remaining
              -1 |              1 second ago |       -1 second remaining
              -0 |                  just now |       0 seconds remaining
               0 |                  just now |       0 seconds remaining
               1 |         1 second from now |        1 second remaining
              10 |       10 seconds from now |      10 seconds remaining
              60 |         1 minute from now |        1 minute remaining
             600 |       10 minutes from now |      10 minutes remaining
            3600 |           1 hour from now |          1 hour remaining
           36000 |         10 hours from now |        10 hours remaining
           86400 |            1 day from now |           1 day remaining
          864000 |           1 week from now |          1 week remaining
         1468800 |          2 weeks from now |         2 weeks remaining
         1488010 |          2 weeks from now |         2 weeks remaining

【讨论】:

    【解决方案3】:

    从 iOS 13 / macOS 10.15 开始,您可以使用RelativeDateTimeFormatter。 感谢@mattt 把它放在你的archived Github README 上。

    import Foundation
    
    let formatter = RelativeDateTimeFormatter()
    formatter.formattingContext = .beginningOfSentence
    
    let date = Date().addingTimeInterval(-67 * 60)
    formatter.string(for: date)! // => "1 hour ago"
    

    【讨论】:

      猜你喜欢
      • 2010-12-02
      • 2023-03-31
      • 2010-09-06
      • 2010-11-27
      • 2017-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多