Date/Time Swift 中的自然语言近似
Date/Time Natural Language Approximation in Swift
我正在尝试使用 Swift.
将 UTC 格式的日期从 API 转换为人类可读的近似格式
我正在寻找类似以下内容的内容:
2015-07-14T13:51:05.423Z
到
About two weeks ago
在 Swift 中最好的方法是什么?虽然最好这可以直接格式化字符串,但我知道这可能需要将字符串转换为 NSDate 对象。
如有任何帮助,我们将不胜感激。
编辑:我的问题已被确定为可能与 another question 重复。 Tom 下面的解决方案是为 Swift 编写的,比根据我的情况创建新方法要优雅得多。
您需要两个步骤。首先,将您的日期字符串转换为 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 日,因此该字符串的结果是 "About 2 weeks"。 allowedUnits
属性是位字段,因此您可以指定任意数量的单位类型。
正如 Tom Harrington 的回答所述,您可以使用 NSDateComponentsFormatter
.
生成时刻或时间间隔的口语表示
但是,如果您想完全按照示例中的问题进行操作,即生成一个 相对于当前时刻的过去时刻的口语表示 ,比如面向时间线的UI,那么好像NSDateComponentsFormatter
不是suitable。正如 stringFromTimeInterval(_:)
的文档所说,时间间隔值 "must be a finite number. Negative numbers are treated as positive numbers when creating the string."
据我所知,最好的选择是 TTTTimeIntervalFormatter
,这是 Mattt Thompson 的 FormatterKit.
中的独立 class
我制作了一个 Xcode 7 playground,RelativeDatePlayground,它将 NSDateFormatter
的输出与 TTTTimeIntervalFormatter
的输出进行比较。这是一个 table 显示不同相对时间的输出(以秒为单位)。如您所见,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
从 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"
我正在尝试使用 Swift.
将 UTC 格式的日期从 API 转换为人类可读的近似格式我正在寻找类似以下内容的内容:
2015-07-14T13:51:05.423Z
到
About two weeks ago
在 Swift 中最好的方法是什么?虽然最好这可以直接格式化字符串,但我知道这可能需要将字符串转换为 NSDate 对象。
如有任何帮助,我们将不胜感激。
编辑:我的问题已被确定为可能与 another question 重复。 Tom 下面的解决方案是为 Swift 编写的,比根据我的情况创建新方法要优雅得多。
您需要两个步骤。首先,将您的日期字符串转换为 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 日,因此该字符串的结果是 "About 2 weeks"。 allowedUnits
属性是位字段,因此您可以指定任意数量的单位类型。
正如 Tom Harrington 的回答所述,您可以使用 NSDateComponentsFormatter
.
但是,如果您想完全按照示例中的问题进行操作,即生成一个 相对于当前时刻的过去时刻的口语表示 ,比如面向时间线的UI,那么好像NSDateComponentsFormatter
不是suitable。正如 stringFromTimeInterval(_:)
的文档所说,时间间隔值 "must be a finite number. Negative numbers are treated as positive numbers when creating the string."
据我所知,最好的选择是 TTTTimeIntervalFormatter
,这是 Mattt Thompson 的 FormatterKit.
我制作了一个 Xcode 7 playground,RelativeDatePlayground,它将 NSDateFormatter
的输出与 TTTTimeIntervalFormatter
的输出进行比较。这是一个 table 显示不同相对时间的输出(以秒为单位)。如您所见,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
从 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"