如何在 swift 中格式化用户显示(类似社交网络)的时间间隔?

How to format time intervals for user display (social network like) in swift?

我有一个时间间隔,比如说,12600,相当于3小时30分钟。我如何格式化任何此类时间间隔,以便仅保留间隔的最高部分(例如,在本例中为小时数)并将正确的区域设置缩写附加到数字。例如10m(10分钟),3d(3天),1y(1年)。


编辑:这里有一些例子:

Time interval in: 90000    Whole string: 1d      String out: 1d
Time interval in: 900      Whole string: 15m     String out: 15m
Time interval in: 13500    Whole String: 3h 45m  String out: 4h

作为一般规则,应用正常的舍入规则(向下舍入 3.4,向上舍入 3.6)。

您可以使用 NSDate 和 NSCalendar。你可以这样说:

let timeInterval:Double = 12600
let calendar = NSCalendar.currentCalendar()
let date = NSDate(timeInterval: -timeInterval, sinceDate: NSDate())
let components = calendar.components([.Year,.Day,.Hour, .Minute, .Second, .Nanosecond], fromDate: date, toDate: NSDate(), options: [])

let hour = components.hour //3
let minute = components.minute //30

根据 duncan 和 rmaddy 的建议使用 NSDateComponentsFormatter

看看 NSDateComponentsFormatter class。它允许您使用 2 个日期或使用 NSTimeInterval 来计算您想要的任何单位,并自动支持不同的语言和区域设置。 SO 中有几篇关于这个主题的帖子。

我为你创建了一个功能!我希望你喜欢它。而且这非常容易实现并且非常可定制。

func totime(time: Double) -> (String) {

var timex = time

var fancytime: String = "a while"

if time < 61 {
    fancytime = "\(timex)s"
} else if time < 3601 {
    timex = timex/60
    timex = round(timex)
    fancytime = "\(timex)m"
} else if time < 86401 {
    timex = timex/3600
    timex = round(timex)
    fancytime = "\(timex)h"
} else if Double(time) < 3.15576E+07 {
    timex = timex/86400
    timex = round(timex)
    fancytime = "\(timex)d"
} else {
    fancytime = "more than one year"
}

fancytime = fancytime.stringByReplacingOccurrencesOfString(".0", withString: "")

return fancytime
}

已测试,完美运行:

print(totime(90000)) // prints "1d"
print(totime(900)) // prints "15m"
print(totime(13500)) // prints "4h"

totime(Double)调用即可。

如果您的目标是较新的 OS 版本(iOS 13.5+、OS X 10.15+),您可以使用 RelativeDateTimeFormatter:

let formatter = RelativeDateTimeFormatter()
formatter.dateTimeStyle = .named

for d in [-12600.0, -90000.0, -900.0, 13500.0] {
    let str = formatter.localizedString(fromTimeInterval: d)
    print("\(d): \(str)")
}

// Output
-12600.0: 3 hours ago
-90000.0: yesterday
-900.0: 15 minutes ago
13500.0: in 3 hours

对于旧的 OS 版本,使用 DateComponentFormatter,自 iOS 8:

起可用
func format(duration: TimeInterval) -> String {
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = [.day, .hour, .minute, .second]
    formatter.unitsStyle = .abbreviated
    formatter.maximumUnitCount = 1

    return formatter.string(from: duration)!
}

for d in [12600.0, 90000.0, 900.0, 13500.0] {
    let str = format(duration: d)
    print("\(d): \(str)")
}

这会打印:

12600.0: 4h
90000.0: 1d
900.0: 15m
13500.0: 4h

Swift 3 分机:

extension TimeInterval {

  func format() -> String? {
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = [.day, .hour, .minute, .second, .nanosecond]
    formatter.unitsStyle = .abbreviated
    formatter.maximumUnitCount = 1
    return formatter.string(from: self)
  }
}

以防万一有人想要.. Swift 4

extension TimeInterval {
    func format(using units: NSCalendar.Unit) -> String? {
        let formatter = DateComponentsFormatter()
        formatter.allowedUnits = units
        formatter.unitsStyle = .abbreviated
        formatter.zeroFormattingBehavior = .pad

        return formatter.string(from: self)
    }
}

用法示例:

let value:TimeInterval =  12600.0
print("\(value.format(using: [.hour, .minute, .second])!)")

结果将是:

3h 30m 0s