问题
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