Como converter um NSTimeInterval (segundos) em minutos
-
19-09-2019 - |
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.
Solução
pseudo-código:
minutes = floor(326.4/60)
seconds = round(326.4 - minutes * 60)
Outras dicas
Breve Descrição
- A resposta de Brian Ramsay é mais conveniente se você só deseja converter em minutos.
- 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
-
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.
-
-
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).
-
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"