Comment convertir un NSTimeInterval (secondes) en minutes

J’ai un certain nombre de secondes qui sont passées d’un certain événement. Il est stocké dans un type de données NSTimeInterval.

Je veux le convertir en minutes et secondes.

Par exemple, j’ai: “326.4” secondes et je veux le convertir dans la chaîne suivante: “5:26”.

Quel est le meilleur moyen d’atteindre cet objective?

Merci.

pseudo-code:

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

Brève description

  1. La réponse de Brian Ramsay est plus pratique si vous voulez seulement convertir en minutes.
  2. Si vous voulez que l’API Cocoa le fasse pour vous et convertisse votre NSTimeInterval non seulement en minutes, mais aussi en jours, mois, semaines, etc. Je pense que c’est une approche plus générique
  3. Utilisez la méthode NSCalendar:

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

    • “Retourne, en tant qu’object NSDateComponents utilisant des composants spécifiés, la différence entre deux dates fournies”. De la documentation de l’API.

  4. Créez 2 NSDate dont la différence est NSTimeInterval que vous voulez convertir. (Si votre NSTimeInterval vient de comparer 2 NSDate, vous n’avez pas besoin de faire cette étape et vous n’avez même pas besoin du NSTimeInterval).

  5. Obtenez vos devis de NSDateComponents

Exemple de code

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

Problèmes connus

  • Trop pour une simple conversion, vous avez raison, mais c’est comme ça que fonctionne l’API.
  • Ma suggestion: si vous vous habituez à gérer vos données de temps en utilisant NSDate et NSCalendar, l’API fera le travail difficile pour vous.

Tout cela semble plus compliqué que nécessaire! Voici un moyen simple et rapide de convertir un intervalle de temps en heures, minutes et secondes:

 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; 

Notez que lorsque vous placez un flottant dans un int, vous obtenez automatiquement floor (), mais vous pouvez l’append aux deux premiers si si vous vous sentez mieux 🙂

Pardonnez-moi d’être une vierge de Stack … Je ne sais pas comment répondre à la réponse de Brian Ramsay …

L’utilisation d’un tour ne fonctionnera pas pour les secondes valeurs comsockets entre 59,5 et 59,99999. La deuxième valeur sera 60 pendant cette période. Utilisez trunc à la place …

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

Si vous ciblez iOS 8 ou OS X 10.10 ou plus, cela devient beaucoup plus facile. La nouvelle classe NSDateComponentsFormatter vous permet de convertir un NSTimeInterval donné de sa valeur en secondes en une chaîne localisée pour afficher l’utilisateur. Par exemple:

Objectif c

 NSTimeInterval interval = 326.4; NSDateComponentsFormatter *componentFormatter = [[NSDateComponentsFormatter alloc] init]; componentFormatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional; componentFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropAll; NSSsortingng *formattedSsortingng = [componentFormatter ssortingngFromTimeInterval:interval]; NSLog(@"%@",formattedSsortingng); // 5:26 

Rapide

 let interval = 326.4 let componentFormatter = NSDateComponentsFormatter() componentFormatter.unitsStyle = .Positional componentFormatter.zeroFormattingBehavior = .DropAll if let formattedSsortingng = componentFormatter.ssortingngFromTimeInterval(interval) { print(formattedSsortingng) // 5:26 } 

NSDateCompnentsFormatter permet également que cette sortie soit plus longue. Plus d’informations peuvent être trouvées dans l’ article NSFormatter de NSHipster . Et selon les classes avec NSTimeInterval vous travaillez déjà (si ce n’est NSTimeInterval ), il peut être plus pratique de passer le formateur d’une instance de NSDateComponents , ou de deux objects NSDate , ce qui peut être fait aussi via les méthodes suivantes.

Objectif c

 NSSsortingng *formattedSsortingng = [componentFormatter ssortingngFromDate:<#(NSDate *)#> toDate:<#(NSDate *)#>]; NSSsortingng *formattedSsortingng = [componentFormatter ssortingngFromDateComponents:<#(NSDateComponents *)#>]; 

Rapide

 if let formattedSsortingng = componentFormatter.ssortingngFromDate(<#T##startDate: NSDate##NSDate#>, toDate: <#T##NSDate#>) { // ... } if let formattedSsortingng = componentFormatter.ssortingngFromDateComponents(<#T##components: NSDateComponents##NSDateComponents#>) { // ... } 

Le code de Brian Ramsay, pseudofied:

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

Voici une version de 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) } 

Peut être utilisé comme ceci:

 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 ssortingngFromDate:timeLater]); NSLog(@"time left: %d hours %d minutes %d seconds", hours,minutes,seconds); 

Les sorties:

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

Puisque c’est essentiellement un double …

Diviser par 60,0 et extraire la partie intégrale et la partie fractionnaire.

La partie intégrale sera le nombre entier de minutes.

Multipliez la partie fractionnaire par 60,0 à nouveau.

Le résultat sera les secondes restantes.

Comment je l’ai fait dans Swift (y compris le formatage de la chaîne pour le montrer comme “01:23”):

 let totalSeconds: Double = someTimeInterval let minutes = Int(floor(totalSeconds / 60)) let seconds = Int(round(totalSeconds % 60)) let timeSsortingng = Ssortingng(format: "%02d:%02d", minutes, seconds) NSLog(timeSsortingng) 

Swift 2 version

 extension NSTimeInterval { func toMM_SS() -> Ssortingng { let interval = self let componentFormatter = NSDateComponentsFormatter() componentFormatter.unitsStyle = .Positional componentFormatter.zeroFormattingBehavior = .Pad componentFormatter.allowedUnits = [.Minute, .Second] return componentFormatter.ssortingngFromTimeInterval(interval) ?? "" } } let duration = 326.4.toMM_SS() print(duration) //"5:26" 

N’oubliez pas que la question d’origine concerne une sortie de chaîne, et non un pseudo-code ou des composants de chaîne individuels.

Je veux le convertir dans la chaîne suivante: “5:26”

Beaucoup de réponses manquent les problèmes d’internationalisation et la plupart font les calculs mathématiques à la main. Tout juste 20ème siècle …

Ne faites pas les maths vous-même (Swift 4)

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

5:26


Effet de levier sur les bibliothèques

Si vous voulez vraiment des composants individuels et du code lisible, jetez un œil à SwiftDate :

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

5


Crédits sur @mickmaccallum et @polarwar pour une utilisation adéquate de DateComponentsFormatter