Вопрос

У меня есть некоторое количество seconds это произошло после определенного события.Он хранится в NSTimeInterval тип данных.

Я хочу преобразовать это в minutes и seconds.

Например, у меня есть:"326,4" секунды, и я хочу преобразовать его в следующую строку:"5:26".

Каков наилучший способ достижения этой цели?

Спасибо.

Это было полезно?

Решение

псевдокод:

minutes = floor(326.4/60)
seconds = round(326.4 - minutes * 60)

Другие советы

Краткое описание

  1. Ответ Брайана Рамзи более удобен, если вы хотите конвертировать только в минуты.
  2. Если вам нужен Cocoa API, сделайте это за себя и преобразуйте ваш NSTimeInterval не только в минуты, но и в дни, месяцы, недели и т.д...Я думаю, что это более общий подход
  3. Используйте метод NSCalendar:

    • (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts

    • "Возвращает в качестве объекта NSDateComponents, использующего указанные компоненты, разницу между двумя предоставленными датами".Из документации API.

  4. Создайте 2 NSDate, разницей между которыми является значение NSTimeInterval, которое вы хотите преобразовать.(Если ваш NSTimeInterval получен в результате сравнения 2 NSDate, вам не нужно выполнять этот шаг, и вам даже не нужен NSTimeInterval).

  5. Получите ваши котировки из 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"
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top