105 votes

Comment convertir un NSTimeInterval (secondes) en minutes ?

J'ai une quantité de seconds qui est passé d'un certain événement. Il est stocké dans un NSTimeInterval type de données.

Je veux le convertir en minutes y seconds .

Par exemple, j'ai : "326.4" secondes et je veux le convertir en la chaîne suivante : "5:26".

Quelle est la meilleure façon d'atteindre cet objectif ?

Merci.

183voto

Albaregar Points 4440

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 Cocoa API le fasse pour vous et convertisse votre NSTimeInterval non seulement en minutes mais aussi en jours, mois, semaine, etc, .... Je pense que ceci 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

    • "Renvoie, sous la forme d'un objet NSDateComponents utilisant les composants spécifiés, la différence entre deux dates fournies". Extrait de la documentation de l'API.

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

  5. Demandez votre devis à 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

  • C'est trop pour une simple conversion, vous avez raison, mais c'est ainsi que fonctionne l'API.
  • Ma suggestion : si vous avez l'habitude de gérer vos données temporelles à l'aide de NSDate et NSCalendar, l'API fera le travail difficile pour vous.

4 votes

C'est définitivement beaucoup de travail pour juste faire une petite conversion, mais cela semble confortable, modulaire et vraiment flexible, votez pour cet exemple de code @Albaregar.

2 votes

+1 Pour une bonne réponse approfondie, cependant ce code est assez cher.

1 votes

+1 ... une mise en garde. Soyez prudent en utilisant ce style de code si vous avez besoin d'arrondir des fractions de secondes. Le comportement par défaut de -[NSCalendar components:fromDate:toDate:options :] peut provoquer des erreurs dans le scénario où le composant toDate a 31,5 secondes (par exemple) d'avance sur le composant fromDate - les composants retournés auront 31 dans le champ secondes. Il existe un paramètre optionnel de NSWrapCalendarComponents, mais d'après l'expérimentation (limitée) que j'ai faite avec ce paramètre, il arrondit à la seconde près plutôt que d'arrondir vers le haut ou vers le bas. Votre expérience peut varier.

147voto

Brian Ramsay Points 4332

Pseudo-code :

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

91 votes

Je pense qu'il est également utile de mentionner qu'un NSTimerInterval est juste un typedef pour double.

4 votes

Voir la réponse d'Albaregar - c'est une meilleure façon de faire (plus de code mais plus flexible, plus facile à maintenir).

1 votes

Ce code est toutefois très coûteux. Pour une conversion rapide d'une durée en secondes, cette réponse est meilleure.

43voto

Prasad Points 171

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 mettez un float dans un int, vous obtenez automatiquement floor(), mais vous pouvez l'ajouter aux deux premiers si cela vous rassure :-)

0 votes

C'est génial ! J'ai essayé le code de Ramsay mais il semble être décalé d'une seconde.

0 votes

Il manque un point-virgule dans votre code mais je n'ai pas pu le modifier pour le corriger.

0 votes

Je pense que votre approche est la meilleure : simple, efficace et légère sur les tics. Parfait.

29voto

StratFan Points 331

Pardonnez-moi d'être un vierge de Stack... Je ne sais pas comment répondre à la réponse de Brian Ramsay...

L'utilisation de l'arrondi ne fonctionnera pas pour les valeurs de seconde comprises entre 59,5 et 59,99999. La deuxième valeur sera 60 pendant cette période. Utilisez plutôt trunc...

 double progress;

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

1 votes

En fait, il suffit de retirer le plancher et le coffre/le rond :)

0 votes

@StratFan Pouvez-vous ajouter des heures à votre réponse ?

17voto

Yang Meyer Points 2054

Le code de Brian Ramsay, dépseudofié :

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

0 votes

Cela ne permet pas de localiser

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X