iOS DateComponentsFormatter - получить использованные единицы
Я хотел бы отформатировать время от секунд до позиционного формата, как 2:05 мин или 1:23 ч или 19 с. У меня проблема с поиском локализованной сокращенной единицы времени. Вот мой код
let secs: Double = 3801
let stopWatchFormatter = DateComponentsFormatter()
stopWatchFormatter.unitsStyle = .positional
stopWatchFormatter.maximumUnitCount = 2
stopWatchFormatter.allowedUnits = [.hour, .minute, .second]
print(stopWatchFormatter.string(from: secs)) // 1:03
stopWatchFormatter.unitsStyle = .short
print(stopWatchFormatter.string(from: secs)) // 1 hr, 3 min
Как вы можете видеть 3801 секунд отформатирован в 1:03, что хорошо, но я не знаю, DateComponentsFormatter
использованные часы или минуты и т. д. Я могу использовать простую логику MOD, чтобы проверить это, но затем наступает сложная часть локализации. Также обратите внимание, что решение MOD бесполезно, если я установлю collapsesLargestUnit
в false
,
2 ответа
DateComponentsFormatter
не поддерживает напрямую нужный формат, который по сути является позиционным форматом, но с первым блоком короткого формата, показанным в конце.
Следующая вспомогательная функция объединяет эти два отдельных результата в то, что вы хотите. Это должно работать с любой локалью, но для подтверждения этого необходимо провести тщательное тестирование.
func formatStopWatchTime(seconds: Double) -> String {
let stopWatchFormatter = DateComponentsFormatter()
stopWatchFormatter.unitsStyle = .positional
stopWatchFormatter.maximumUnitCount = 2
stopWatchFormatter.allowedUnits = [.hour, .minute, .second]
var pos = stopWatchFormatter.string(from: seconds)!
// Work around a bug where some values return 3 units despite only requesting 2 units
let parts = pos.components(separatedBy: CharacterSet.decimalDigits.inverted)
if parts.count > 2 {
let seps = pos.components(separatedBy: .decimalDigits).filter { !$0.isEmpty }
pos = parts[0..<2].joined(separator: seps[0])
}
stopWatchFormatter.maximumUnitCount = 1
stopWatchFormatter.unitsStyle = .short
let unit = stopWatchFormatter.string(from: seconds)!
// Replace the digits in the unit result with the pos result
let res = unit.replacingOccurrences(of: "[\\d]+", with: pos, options: [.regularExpression])
return res
}
print(formatStopWatchTime(seconds: 3801))
Выход:
1:03
Как я понимаю, вам не нужна строка, а DateComponent:
let dateA = Date(timeIntervalSince1970: 0)
let dateB = Date(timeIntervalSince1970: timeInterval)
let components = Calendar.current.dateComponents([.hour, .minute, .second], from: dateA, to: dateB)