Как преобразовать NSTimeInterval (секунды) в минуты
-
19-09-2019 - |
Вопрос
У меня есть некоторое количество seconds
это произошло после определенного события.Он хранится в NSTimeInterval
тип данных.
Я хочу преобразовать это в minutes
и seconds
.
Например, у меня есть:"326,4" секунды, и я хочу преобразовать его в следующую строку:"5:26".
Каков наилучший способ достижения этой цели?
Спасибо.
Решение
псевдокод:
minutes = floor(326.4/60)
seconds = round(326.4 - minutes * 60)
Другие советы
Краткое описание
- Ответ Брайана Рамзи более удобен, если вы хотите конвертировать только в минуты.
- Если вам нужен Cocoa API, сделайте это за себя и преобразуйте ваш NSTimeInterval не только в минуты, но и в дни, месяцы, недели и т.д...Я думаю, что это более общий подход
Используйте метод NSCalendar:
(NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts
"Возвращает в качестве объекта NSDateComponents, использующего указанные компоненты, разницу между двумя предоставленными датами".Из документации API.
Создайте 2 NSDate, разницей между которыми является значение NSTimeInterval, которое вы хотите преобразовать.(Если ваш NSTimeInterval получен в результате сравнения 2 NSDate, вам не нужно выполнять этот шаг, и вам даже не нужен NSTimeInterval).
Получите ваши котировки из NSDateComponents
Пример кода
// The time interval
NSTimeInterval theTimeInterval = 326.4;
// Get the system calendar
NSCalendar *sysCalendar = [NSCalendar currentCalendar];
// Create the NSDates
NSDate *date1 = [[NSDate alloc] init];
NSDate *date2 = [[NSDate alloc] initWithTimeInterval:theTimeInterval sinceDate:date1];
// Get conversion to months, days, hours, minutes
unsigned int unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;
NSDateComponents *conversionInfo = [sysCalendar components:unitFlags fromDate:date1 toDate:date2 options:0];
NSLog(@"Conversion: %dmin %dhours %ddays %dmoths",[conversionInfo minute], [conversionInfo hour], [conversionInfo day], [conversionInfo month]);
[date1 release];
[date2 release];
Известные проблемы
- Вы правы, слишком много для простого преобразования, но именно так работает API.
- Мое предложение:если вы привыкнете управлять своими временными данными с помощью NSDate и NSCalendar, API сделает всю тяжелую работу за вас.
Все это выглядит сложнее, чем должно быть на самом деле!Вот короткий и приятный способ преобразовать временной интервал в часы, минуты и секунды:
NSTimeInterval timeInterval = 326.4;
long seconds = lroundf(timeInterval); // Since modulo operator (%) below needs int or long
int hour = seconds / 3600;
int mins = (seconds % 3600) / 60;
int secs = seconds % 60;
Примечание: когда вы помещаете float в int, вы автоматически получаете floor(), но вы можете добавить его к первым двум, если вам станет легче :-)
Прости меня за то, что я непорочная девственница...Я не уверен, как ответить на ответ Брайана Рамзи...
Использование round не будет работать для вторых значений между 59.5 и 59.99999.Второе значение в течение этого периода будет равно 60.Вместо этого используйте trunc...
double progress;
int minutes = floor(progress/60);
int seconds = trunc(progress - minutes * 60);
Если вы ориентируетесь на iOS 8 или OS X 10.10 или выше, это становится намного проще.Новый NSDateComponentsFormatter
класс позволяет вам преобразовать заданный NSTimeInterval
от его значения в секундах до локализованной строки для отображения пользователю.Например:
Цель-C
NSTimeInterval interval = 326.4;
NSDateComponentsFormatter *componentFormatter = [[NSDateComponentsFormatter alloc] init];
componentFormatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
componentFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropAll;
NSString *formattedString = [componentFormatter stringFromTimeInterval:interval];
NSLog(@"%@",formattedString); // 5:26
Быстрый
let interval = 326.4
let componentFormatter = NSDateComponentsFormatter()
componentFormatter.unitsStyle = .Positional
componentFormatter.zeroFormattingBehavior = .DropAll
if let formattedString = componentFormatter.stringFromTimeInterval(interval) {
print(formattedString) // 5:26
}
NSDateCompnentsFormatter
также позволяет использовать этот вывод в более длинных формах.Более подробную информацию можно найти в NSHipster Статья NSFormatter.И в зависимости от того, с какими классами вы уже работаете (если нет NSTimeInterval
), возможно, было бы удобнее передать программе форматирования экземпляр NSDateComponents
, или два NSDate
объекты, которые также могут быть выполнены с помощью следующих методов.
Цель-C
NSString *formattedString = [componentFormatter stringFromDate:<#(NSDate *)#> toDate:<#(NSDate *)#>];
NSString *formattedString = [componentFormatter stringFromDateComponents:<#(NSDateComponents *)#>];
Быстрый
if let formattedString = componentFormatter.stringFromDate(<#T##startDate: NSDate##NSDate#>, toDate: <#T##NSDate#>) {
// ...
}
if let formattedString = componentFormatter.stringFromDateComponents(<#T##components: NSDateComponents##NSDateComponents#>) {
// ...
}
Брайан Рамсей, де-pseudofied:
- (NSString*)formattedStringForDuration:(NSTimeInterval)duration
{
NSInteger minutes = floor(duration/60);
NSInteger seconds = round(duration - minutes * 60);
return [NSString stringWithFormat:@"%d:%02d", minutes, seconds];
}
Вот быстрая версия:
func durationsBySecond(seconds s: Int) -> (days:Int,hours:Int,minutes:Int,seconds:Int) {
return (s / (24 * 3600),(s % (24 * 3600)) / 3600, s % 3600 / 60, s % 60)
}
Может быть использован следующим образом:
let (d,h,m,s) = durationsBySecond(seconds: duration)
println("time left: \(d) days \(h) hours \(m) minutes \(s) seconds")
NSDate *timeLater = [NSDate dateWithTimeIntervalSinceNow:60*90];
NSTimeInterval duration = [timeLater timeIntervalSinceNow];
NSInteger hours = floor(duration/(60*60));
NSInteger minutes = floor((duration/60) - hours * 60);
NSInteger seconds = floor(duration - (minutes * 60) - (hours * 60 * 60));
NSLog(@"timeLater: %@", [dateFormatter stringFromDate:timeLater]);
NSLog(@"time left: %d hours %d minutes %d seconds", hours,minutes,seconds);
Результаты:
timeLater: 22:27
timeLeft: 1 hours 29 minutes 59 seconds
Поскольку это, по сути, дубль...
Разделите на 60,0 и извлеките целую и дробную части.
Неотъемлемой частью будет являться все количество минут.
Снова умножьте дробную часть на 60,0.
Результатом будут оставшиеся секунды.
Помните, что исходный вопрос касается вывода строки, а не псевдокода или отдельных компонентов строки.
Я хочу преобразовать его в следующую строку:"5:26"
Во многих ответах отсутствуют вопросы интернационализации, и большинство из них выполняют математические вычисления вручную.Все просто, как в 20 веке...
Не делайте математику самостоятельно (Swift 4)
let timeInterval: TimeInterval = 326.4
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.unitsStyle = .positional
if let formatted = dateComponentsFormatter.string(from: timeInterval) {
print(formatted)
}
5:26
Рычаги воздействия на библиотеки
Если вам действительно нужны отдельные компоненты и приятно читаемый код, ознакомьтесь Быстрая дата:
import SwiftDate
...
if let minutes = Int(timeInterval).seconds.in(.minute) {
print("\(minutes)")
}
5
Кредиты для @mickmaccallum и @polarwar для адекватного использования DateComponentsFormatter
Как я сделал это в Swift (включая форматирование строки, чтобы показать ее как "01: 23"):
let totalSeconds: Double = someTimeInterval
let minutes = Int(floor(totalSeconds / 60))
let seconds = Int(round(totalSeconds % 60))
let timeString = String(format: "%02d:%02d", minutes, seconds)
NSLog(timeString)
Версия Swift 2
extension NSTimeInterval {
func toMM_SS() -> String {
let interval = self
let componentFormatter = NSDateComponentsFormatter()
componentFormatter.unitsStyle = .Positional
componentFormatter.zeroFormattingBehavior = .Pad
componentFormatter.allowedUnits = [.Minute, .Second]
return componentFormatter.stringFromTimeInterval(interval) ?? ""
}
}
let duration = 326.4.toMM_SS()
print(duration) //"5:26"