NSDateComponentsFormatter stringFromTimeInterval возвращает неверную строку для интервалов менее 1 минуты
Я использую NSDateComponentsFormatter на iOS 8, и я заметил возможную ошибку в реализации метода stringFromTimeInterval:
, но я не могу сказать это точно.
Вот как я установил форматтер:
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDefault;
formatter.allowedUnits = NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
formatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
Теперь, когда я передаю менее 60 секунд методу stringFromTimeInterval:
, форматтер возвращает либо 1
, либо 01
, что, очевидно, неверно, он должен возвращать что-то вроде 0:XX
.
Я также заметил, что, изменив unitsStyle
на что-либо, кроме NSDateComponentsFormatterUnitsStylePositional
, метод вернет правильную строку!
Пример:
С unitsStyle = NSDateComponentsFormatterUnitsStylePositional
:
(lldb) po [formatter stringFromTimeInterval:12]
= "1"
= > Должен возвращать "0:12"!!
С unitsStyle = NSDateComponentsFormatterUnitsStyleAbbreviated
:
(lldb) po [formatter stringFromTimeInterval:12]
= "12 s"
= > Правильно!
Это позволяет мне думать, что это ошибка в реализации Apple API, или я чего-то не хватает?
Ответы
Ответ 1
Кажется, что все еще проблема с iOS 8.3 и Xcode 6.3.
Тем не менее, есть способ обойти его, что, если не идеально, по крайней мере позволяет получить правильное форматирование, не занимаясь самими релевантными компонентами времени.
Вот пример обходного пути в Swift (который вы можете протестировать на игровой площадке)
let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = .Positional
formatter.zeroFormattingBehavior = .Pad
formatter.allowedUnits = .CalendarUnitMinute | .CalendarUnitSecond
Вызов let string = formatter.stringFromTimeInterval(4)
будет печатать "00:04".
Вызов let string = formatter.stringFromTimeInterval(88)
будет печатать "01:28".
Теперь вы можете играть с allowedUnits
в зависимости от того, у вас есть более 1 часа или 1 день. Например, в классе, который имеет свойство formatter
:
func updateTimeFormatterForTime(time: NSTimeInterval) {
if time > 3600 && time < 24 * 3600 {
self.formatter.allowedUnits = .CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond
} else if time > 24 * 3600 {
self.formatter.allowedUnits = .CalendarUnitDay | .CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond
}
}
Ответ 2
NSDateComponentsFormatterZeroFormattingBehaviorDefault означает падение ведущих нулей, добавление других нулей для стиля позиционных единиц.
например. с значениями allowedUnits в вашем коде, результат [formatter stringFromTimeInterval: 120] равен "2:00" вместо "0d 0:02:00",
потому что объект форматирования удалил все начальные нулевые значения.
Если вы хотите зарезервировать нулевые значения, вы можете использовать NSDateComponentsFormatterZeroFormattingBehaviorNone
Для чего результат
Ответ 3
Как насчет этой функции:
func stringFromTimeInterval(interval: NSTimeInterval) -> String {
let ti: Int = Int(interval)
let seconds: Int = ti % 60
let minutes: Int = (ti / 60) % 60
let hours: Int = (ti / 3600)
var time: String? = nil
if hours > 0 {
time = String(format: "%02i:%02i:%02i", hours, minutes, seconds)
}
else {
time = String(format: "%02i:%02i", minutes, seconds)
}
return time!
}
Возвращает время в этой отформатированной строке: 59:04 (мм: ss) или 09:01:34 (чч: мм: сс)