Swift中的日期/时间自然语言逼近

时间:2015-07-28 20:15:55

标签: swift cocoa-touch datetime nsdateformatter swift2

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

我正在寻找以下内容:

  

2015-07-14T13:51:05.423Z

  

大约两周前

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

非常感谢任何帮助。

编辑:我的问题已被确定为another question的可能副本。下面的Tom解决方案是为Swift编写的,并且比根据我的情况创建一个新方法更优雅。

3 个答案:

答案 0 :(得分:31)

您需要两个步骤。首先,将日期字符串转换为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属性是一个位字段,因此您可以指定任意数量的单位类型。

答案 1 :(得分:3)

正如Tom Harrington的回答说明,您可以使用NSDateComponentsFormatter生成时刻或时间间隔的口语表示。

但是,如果你想要完全解决问题在其示例中提出的问题,那就是产生一个过去时刻的口语表示,相对于当前时刻,就像时间轴一样面向用户界面,似乎NSDateComponentsFormatter似乎不合适。正如stringFromTimeInterval(_:)的文档所述,时间间隔值"必须是有限数。创建字符串时,负数被视为正数。"

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

我制作了一个Xcode 7游乐场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

答案 2 :(得分:0)

从 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"