简体   繁体   English

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

[英]Date/Time Natural Language Approximation in Swift

I am attempting to convert a UTC formatted date from an API to a human-readable approximation format using Swift.我正在尝试使用 Swift 将 UTC 格式的日期从 API 转换为人类可读的近似格式。

I'm looking for something like the following:我正在寻找类似以下内容:

2015-07-14T13:51:05.423Z 2015-07-14T13:51:05.423Z

to

About two weeks ago大约两周前

What is the best approach to this in Swift? Swift 中最好的方法是什么? While optimally this could format strings directly, I understand that this will probably require casting the string to a NSDate object.虽然最佳情况下这可以直接格式化字符串,但我知道这可能需要将字符串转换为 NSDate 对象。

Any help would be greatly appreciated.任何帮助将不胜感激。

EDIT: My question had been identified as a possible duplicate of another question .编辑:我的问题已被确定为另一个问题的可能重复。 Tom's solution below is written for Swift and much more elegant than creating a new method in regards to my situation.下面汤姆的解决方案是为 Swift 编写的,比针对我的情况创建新方法要优雅得多。

You need two steps.你需要两个步骤。 First, convert your date string to an NSDate :首先,将您的日期字符串转换为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)

(If that's not an exact representation of the strings you get, you'll have to change the date format string to get this to convert). (如果这不是您获得的字符串的精确表示,则必须更改日期格式字符串才能进行转换)。

Next, use NSDateComponentsFormatter to get your desired string:接下来,使用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())
}

Today is July 28, so the result for that string is "About 2 weeks".今天是 7 月 28 日,因此该字符串的结果是“大约 2 周”。 The allowedUnits attribute is a bit field, so you can specify as many unit types as you want to allow. allowedUnits属性是一个位字段,因此您可以指定任意数量的单位类型。

As Tom Harrington's answer notes, you can produce a colloquial representation of a moment or a time interval using NSDateComponentsFormatter .正如 Tom Harrington 的回答所指出的,您可以使用NSDateComponentsFormatter生成时刻或时间间隔的口语表示。

However, if you want to do exactly what the question asks in its example, which is to produce a colloquial representation of a moment in the past, relative to the present moment , like for a timeline-oriented UI, then it seems like NSDateComponentsFormatter is not suitable.但是,如果您想完全按照示例中的问题进行操作,即生成过去时刻相对于当前时刻口语表示,例如面向时间轴的 UI,那么NSDateComponentsFormatter似乎是不合适。 As the documentation for stringFromTimeInterval(_:) says, the time interval value "must be a finite number. Negative numbers are treated as positive numbers when creating the string."正如stringFromTimeInterval(_:)的文档所说,时间间隔值“必须是一个有限数。在创建字符串时,负数被视为正数。”

As near as I can tell, the best choice is TTTTimeIntervalFormatter , a standalone class in Mattt Thompson's FormatterKit .据我所知,最好的选择是TTTTimeIntervalFormatter ,这是 Mattt Thompson 的FormatterKit 中的一个独立类。

I have produced an Xcode 7 playground, RelativeDatePlayground , that compares the outputs of NSDateFormatter output to TTTTimeIntervalFormatter .我制作了一个 Xcode 7 playground, RelativeDatePlayground ,它将NSDateFormatter输出的输出与TTTTimeIntervalFormatter进行比较。 Here is a table showing output for different relative times in seconds.这是一个表格,显示了不同相对时间的输出(以秒为单位)。 As you can see, NSDateComponentsFormatter does not seem to handle past moments or the present moment well:如您所见, 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

Since iOS 13 / macOS 10.15 you can use RelativeDateTimeFormatter .从 iOS 13 / macOS 10.15 开始,您可以使用RelativeDateTimeFormatter Thanks @mattt for putting this on your archived Github README .感谢 @mattt 把它放在你存档的 Github README 上

import Foundation

let formatter = RelativeDateTimeFormatter()
formatter.formattingContext = .beginningOfSentence

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM