86 votes

NSTimeInterval à HH:mm:ss ?

Si j'ai un NSTimeInterval réglé sur 200.0, existe-t-il un moyen de le convertir en 00:03:20 ? Je pensais pouvoir initialiser une NSDate avec cette valeur et utiliser ensuite NSDateFormatter en utilisant HH:mm:ss. Ma question est la suivante : existe-t-il un moyen rapide de le faire ou dois-je décomposer moi-même le nombre et utiliser le formatage NSDateFormatter en utilisant HH:mm:ss ? [NSString stringWithFormat: %02d:%02d:%02d, myHour, myMin, mySec] ?

200voto

Matthias Bauch Points 52145

Pas besoin d'utiliser NSDateFormatter ou autre chose que la division et le modulo. NSTimeInterval est juste un double contenant des secondes.

Swift

func stringFromTimeInterval(interval: NSTimeInterval) -> String {
    let interval = Int(interval)
    let seconds = interval % 60
    let minutes = (interval / 60) % 60
    let hours = (interval / 3600)
    return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
}

Objectif-C

- (NSString *)stringFromTimeInterval:(NSTimeInterval)interval {
    NSInteger ti = (NSInteger)interval;
    NSInteger seconds = ti % 60;
    NSInteger minutes = (ti / 60) % 60;
    NSInteger hours = (ti / 3600);
    return [NSString stringWithFormat:@"%02ld:%02ld:%02ld", (long)hours, (long)minutes, (long)seconds];
}

0 votes

Merci beaucoup, c'est ce que je pensais mais je voulais juste vérifier que je ne manquais pas quelque chose déjà inclus dans le SDK iOS.

1 votes

Je tiens à souligner que " :" ne fonctionne comme délimiteur qu'en anglais et dans certaines autres langues. Le finnois, par exemple, utilise "." - comme ceci "15.02.59".

0 votes

@sgosha, exactement, normalement Apple tend à fournir des formateurs pour ces derniers. Devrais-je plutôt utiliser une chaîne localisée pour le formatage ?

106voto

jrc Points 1834

Sous iOS 8, utilisez NSDateComponentsFormatter .

NSDateComponentsFormatter *dateComponentsFormatter = [[NSDateComponentsFormatter alloc] init];
NSLog(@"%@", [dateComponentsFormatter stringFromTimeInterval:200.0]);

Les sorties "3:20".

NSDateComponentsFormatter *dateComponentsFormatter = [[NSDateComponentsFormatter alloc] init];
dateComponentsFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
dateComponentsFormatter.allowedUnits = (NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond);
NSLog(@"%@", [dateComponentsFormatter stringFromTimeInterval:200.0]);

Les sorties "0:03:20".

2 votes

Belle mise à jour. Mais s'il s'agit vraiment d'un calcul aussi simple, l'utilisation de ces objets n'entraînerait-elle pas une surcharge énorme (tant qu'il n'y a pas de format dynamique) ?

2 votes

Vous avez besoin de la mise en forme pour que la chaîne de caractères apparaisse correctement dans différentes langues, etc.

0 votes

Vraiment un petit commentaire, mais il est bizarre de donner un exemple de fonction C pour la question ObjectiveC. Cela vaut probablement la peine de le changer en format ObjectiveC ?

18voto

Scott Gardner Points 692

Swift 3 version de onmyway133 La réponse de la Commission :

import Foundation

func format(_ duration: TimeInterval) -> String {
    let formatter = DateComponentsFormatter()
    formatter.zeroFormattingBehavior = .pad
    formatter.allowedUnits = [.minute, .second]

    if duration >= 3600 {
        formatter.allowedUnits.insert(.hour)
    }

    return formatter.string(from: duration)!
}

print(format(12)) // 0:12
print(format(65)) // 1:05
print(format(1750)) // 29:10
print(format(3890)) // 1:04:50
print(format(45720)) // 12:42:00

10voto

Roshit Points 1162

Quelques lignes de code supplémentaires, mais je pense que l'utilisation de NSDateComponents donnera une valeur plus précise.

- (NSString *)getTimeRepresentationFromDate:(NSDate *)iDate withTimeInterval:(NSTimeInterval)iTimeInterval {
    NSString *aReturnValue = nil;
    NSDate *aNewDate = [iDate dateByAddingTimeInterval:iTimeInterval]; 

    unsigned int theUnits = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSCalendar *aCalender = [NSCalendar currentCalendar];
    NSDateComponents *aDateComponents = [aCalender components:theUnits fromDate:iDate toDate:aNewDate options:0];

    aReturnValue = [NSString stringWithFormat:@"%d:%d:%d", [aDateComponents hour], [aDateComponents minute], [aDateComponents second]];

    return aReturnValue;
}

0 votes

La méthode ci-dessus utilise les 2 dates à partir desquelles le TimeInterval est créé. Vous pouvez également passer [NSDate date] au paramètre iDate comme valeur par défaut.

2 votes

En quoi cela est-il "plus précis" que la méthode utilisée par @matthias-bauch ?

1 votes

Avec cette méthode, vous obtenez l'intervalle de temps en secondes, heures, minutes, c'est-à-dire en termes de 60 alors que la réponse de @matthias-bauch vous donne en termes décimaux ; par exemple, si vous attendez suffisamment longtemps, vous verrez 1 min 79 s au lieu de 2 min 19 s.

8voto

onmyway133 Points 2196

Sur Swift 2 , iOS 8+ . Cela permet de s'assurer que nous ne montrons l'heure que lorsque c'est nécessaire

func format(duration: NSTimeInterval) -> String {
  let formatter = NSDateComponentsFormatter()
  formatter.zeroFormattingBehavior = .Pad

  if duration >= 3600 {
    formatter.allowedUnits = [.Hour, .Minute, .Second]
  } else {
    formatter.allowedUnits = [.Minute, .Second]
  }

  return formatter.stringFromTimeInterval(duration) ?? ""
}

Donc vous avez

print(format(12)) // 0:12
print(format(65)) // 1:05
print(format(1750)) // 29:10
print(format(3890)) // 1:04:50
print(format(45720)) // 12:42:00

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