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
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.
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).
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
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 …
let timeInterval: TimeInterval = 326.4 let dateComponentsFormatter = DateComponentsFormatter() dateComponentsFormatter.unitsStyle = .positional if let formatted = dateComponentsFormatter.ssortingng(from: timeInterval) { print(formatted) }
5:26
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