Pergunta

Eu tenho uma quantidade de seconds que passou de um determinado evento. É armazenado em um tipo de dados NSTimeInterval.

Eu quero convertê-lo em minutes e seconds.

Por exemplo eu tenho: "326,4" segundos e eu quero convertê-lo para o seguinte texto: "05:26".

O que é a melhor maneira de alcançar este objetivo?

Graças.

Foi útil?

Solução

pseudo-código:

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

Outras dicas

Breve Descrição

  1. A resposta de Brian Ramsay é mais conveniente se você só deseja converter em minutos.
  2. Se você quiser Cocoa API fazer isso por você e converter seu NSTimeInterval não só para minutos, mas também para dias, meses, semanas, etc, ... Acho que esta é uma abordagem mais genérica
  3. Use o método NSCalendar:

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

    • "Retorna, como um NSDateComponents objeto usando componentes especificados, a diferença entre duas datas fornecidas". A partir da documentação da API.

  4. Criar 2 NSDate cuja diferença é o NSTimeInterval você deseja converter. (Se o seu NSTimeInterval vem comparando 2 NSDate você não precisa fazer esse passo, e você não precisa mesmo do NSTimeInterval).

  5. Obter suas citações de NSDateComponents

Exemplo de código

// 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];

Problemas conhecidos

  • É muito para apenas uma conversão, você está certo, mas é assim que as obras de API.
  • A minha sugestão:. Se você se acostumar a gerenciar seus dados em tempo usando NSDate e NSCalendar, a API irá fazer o trabalho duro para você

Todos estes olhar mais complicado do que eles precisam para ser! Aqui está uma maneira curta e doce para converter um intervalo de tempo em horas, minutos e segundos:

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;

Nota quando você colocar uma bóia em um int, você consegue andar () automaticamente, mas você pode adicioná-lo aos dois primeiros, se se faz sentir melhor: -)

Perdoe-me por ser virgem Stack ... Eu não sei como responder a resposta de Brian Ramsay ...

Usando rodada não vai funcionar para o segundo valores entre 59,5 e 59,99999. O segundo valor será de 60 durante este período. Use trunc vez ...

 double progress;

 int minutes = floor(progress/60);
 int seconds = trunc(progress - minutes * 60);

Se você está alvejando em ou acima iOS 8 ou OS X 10.10, isso ficou muito mais fácil. A nova classe NSDateComponentsFormatter lhe permite converter um dado NSTimeInterval de seu valor em segundos para uma cadeia localizada para mostrar ao usuário. Por exemplo:

Objective-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

Swift

let interval = 326.4

let componentFormatter = NSDateComponentsFormatter()

componentFormatter.unitsStyle = .Positional
componentFormatter.zeroFormattingBehavior = .DropAll

if let formattedString = componentFormatter.stringFromTimeInterval(interval) {
    print(formattedString) // 5:26
}

NSDateCompnentsFormatter também permite a esta saída seja em formas mais longas. Mais informações podem ser encontradas no do NSHipster NSFormatter artigo . E dependendo do que as classes que você já está trabalhando com (se não NSTimeInterval), pode ser mais conveniente para passar o formatador uma instância de NSDateComponents ou dois objetos NSDate, que pode ser feito também através dos seguintes métodos.

Objective-C

NSString *formattedString = [componentFormatter stringFromDate:<#(NSDate *)#> toDate:<#(NSDate *)#>];
NSString *formattedString = [componentFormatter stringFromDateComponents:<#(NSDateComponents *)#>];

Swift

if let formattedString = componentFormatter.stringFromDate(<#T##startDate: NSDate##NSDate#>, toDate: <#T##NSDate#>) {
    // ...
}

if let formattedString = componentFormatter.stringFromDateComponents(<#T##components: NSDateComponents##NSDateComponents#>) {
    // ...
}

código de Brian Ramsay, de-pseudofied:

- (NSString*)formattedStringForDuration:(NSTimeInterval)duration
{
    NSInteger minutes = floor(duration/60);
    NSInteger seconds = round(duration - minutes * 60);
    return [NSString stringWithFormat:@"%d:%02d", minutes, seconds];
}

Aqui está uma versão Swift:

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)
}

Pode ser usado como este:

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);

Saídas:

timeLater: 22:27
timeLeft: 1 hours 29 minutes  59 seconds

Uma vez que é essencialmente um duplo ...

Dividir por 60,0 e extrair a parte integrante e a parte fracionária.

A parte integrante será o número total de minutos.

Multiply a parte fracionária por 60,0 novamente.

O resultado será os segundos restantes.

Lembre-se que a pergunta original é sobre a saída de string, não pseudo-código ou cordas componentes individuais.

Eu quero convertê-lo para o seguinte texto: "5:26"

Muitas respostas estão faltando as questões de internacionalização, e mais fazendo os cálculos matemáticos com a mão. Todos século apenas para 20 ...

Não faça você mesmo a matemática (Swift 4)

let timeInterval: TimeInterval = 326.4
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.unitsStyle = .positional
if let formatted = dateComponentsFormatter.string(from: timeInterval) {
    print(formatted)
}

05:26


Leverage em bibliotecas

Se você realmente quer componentes individuais e código agradavelmente legível, veja SwiftDate :

import SwiftDate
...
if let minutes = Int(timeInterval).seconds.in(.minute) {
    print("\(minutes)")
}

5


Créditos para @mickmaccallum e @ polarwar para o uso adequado de DateComponentsFormatter

Como eu fiz isso em Swift (incluindo a cadeia de formatação para mostrá-lo como "1: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)

Versão 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"
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top