Как форматировать временные интервалы для пользовательского отображения (например, в социальной сети)?
У меня есть временной интервал, скажем, 12600, что эквивалентно 3 часам 30 минут. Как я мог отформатировать любой такой временной интервал, чтобы сохранить только самую большую часть интервала (например, в этом случае цифра, часы) и добавить к этому правилу аббревиатуру правильной локали. Например, 10 м (10 минут), 3d (3 дня), 1 год (1 год).
EDIT: Вот несколько примеров:
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 раунда).
Ответы
Ответ 1
Используйте 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
Ответ 2
Расширение 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)
}
}
Ответ 3
На всякий случай, если кто-то захочет. 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
Ответ 4
Вы можете использовать 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
Ответ 5
Взгляните на класс NSDateComponentsFormatter
. Он позволяет вам рассчитать любые единицы, которые вы хотите либо с использованием двух дат, либо с использованием NSTimeInterval, и автоматически поддерживать разные языки и локали. Там было несколько сообщений здесь в SO по этому вопросу.
Ответ 6
Я создал для вас функцию! Я надеюсь тебе понравится. И это очень легко реализовать и очень настраиваемый.
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)
.