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

送分小仙女□ 提交于 2019-12-04 15:59:14

问题


I have a time interval, say, 12600, which is equivalent to 3 hours 30 minutes. How could I format any such time interval so that only the highest part of the interval (for example in this case figure, the hours) is kept and have the correct locale abbreviation be appended to the number. For example 10m (10 minutes), 3d (3 days), 1y (1 years).


EDIT: Here are some examples:

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

As a general rule, apply the normal rounding rules (3.4 rounds down, 3.6 rounds up).


回答1:


Use DateComponentFormatter, available since 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)")
}

This prints:

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



回答2:


Swift 3 extension:

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)
  }
}



回答3:


Just in case anyone wants it.. 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)
    }
}

Example usage:

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

and the result will be:

3h 30m 0s



回答4:


Take a look at the NSDateComponentsFormatter class. It lets you calculate whatever units you want either using 2 dates or using an NSTimeInterval, and supports different languages and locales automatically. There have been a couple of posts here in SO on the subject.




回答5:


You can use NSDate and NSCalendar. You can say something like:

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

Per duncan's and rmaddy's suggestions use NSDateComponentsFormatter




回答6:


I created a function for you! I hope you like it. And this is super easy to implement and very customizable.

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
}

Tested, and it works flawlessly:

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

Just call it with totime(Double).



来源:https://stackoverflow.com/questions/35999022/how-to-format-time-intervals-for-user-display-social-network-like-in-swift

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!