55 votes

Comment décomposer un NSTimeInterval en année, mois, jours, heures, minutes et secondes sur iPhone?

J'ai un intervalle de temps qui s'étend sur des années et je veux que tous les composants à partir d'année de secondes.

Ma première pensée est pour integer division de l'intervalle de temps en secondes dans une année, déduire de l'exécution d'un total de secondes, divisez-le par secondes dans un mois, déduire de la total en cours d'exécution et ainsi de suite.

Qui semble compliqué et j'ai lu que chaque fois que vous faites quelque chose qui semble compliquée, il y a probablement une méthode intégrée.

Est-il?

J'ai intégré Alex 2ème méthode dans mon code.

C'est dans une méthode appelée par un UIDatePicker dans mon interface.

NSDate *now = [NSDate date];
NSDate *then = self.datePicker.date;
NSTimeInterval howLong = [now timeIntervalSinceDate:then];

NSDate *date = [NSDate dateWithTimeIntervalSince1970:howLong];
NSString *dateStr = [date description];
const char *dateStrPtr = [dateStr UTF8String];
int year, month, day, hour, minute, sec;

sscanf(dateStrPtr, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &sec);
year -= 1970;

NSLog(@"%d years\n%d months\n%d days\n%d hours\n%d minutes\n%d seconds", year, month, day, hour, minute, sec);

Lorsque j'ai mis le sélecteur de date à date 1 an et 1 jour dans le passé, j'obtiens:

1 ans 1 mois 1 jours 16 heures 0 minutes 20 secondes

qui est de 1 mois et 16 heures. Si j'ai mis le sélecteur de date pour 1 journée dans le passé, je suis en congé du même montant.

Mise à jour: j'ai une application qui calcule votre âge en années, compte tenu de votre anniversaire (à partir d'un UIDatePicker), mais il était souvent coupé. Cela prouve, il y a une inexactitude, mais je n'arrive pas à comprendre d'où il vient, pouvez-vous?

100voto

Albaregar Points 4440

Brève Description

  1. Juste une autre approche pour compléter la réponse de JBRWilkinson mais en ajoutant un peu de code. Il peut également, offre une solution Alex Reynolds commentaire.

  2. Utilisation NSCalendar méthode:

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

    • "Retourne, comme un NSDateComponents objet à l'aide de composants spécifiés, la différence entre les deux fourni des dates". (À partir de la documentation de l'API).

  3. Créer 2 NSDate dont la différence est la NSTimeInterval vous voulez briser. (Si votre NSTimeInterval vient de la comparaison de 2 NSDate vous n'avez pas besoin de faire cette étape, et vous n'avez même pas besoin de la NSTimeInterval, il suffit d'appliquer les dates pour le NSCalendar méthode).

  4. Obtenez vos devis de NSDateComponents

Exemple De Code

// The time interval 
NSTimeInterval theTimeInterval = ...;

// 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 *breakdownInfo = [sysCalendar components:unitFlags fromDate:date1  toDate:date2  options:0];

NSLog(@"Break down: %d min : %d hours : %d days : %d months",[breakdownInfo minute], [breakdownInfo hour], [breakdownInfo day], [breakdownInfo month]);

[date1 release];
[date2 release];

17voto

vikingosegundo Points 30323

Ce code prend en compte l’heure du coucher du soleil et d’autres choses désagréables.

 NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorianCalendar components: (NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit )
                                                    fromDate:startDate
                                                      toDate:[NSDate date]
                                                     options:0];


NSLog(@"%ld", [components year]);
NSLog(@"%ld", [components month]);
NSLog(@"%ld", [components day]);
NSLog(@"%ld", [components hour]);
NSLog(@"%ld", [components minute]);
NSLog(@"%ld", [components second]);
 

4voto

JBRWilkinson Points 3155

Convertissez votre intervalle en NSDate en utilisant + dateWithIntervalSince1970, obtenez les composants de date en utilisant la méthode -componentsFromDate de NSCalendar.

Référence du SDK

3voto

doogilasovich Points 59

Cela fonctionne pour moi:

     float *lenghInSeconds = 2345.234513;
    NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:lenghInSeconds];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];


    [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];

    [formatter setDateFormat:@"HH:mm:ss"];
    NSLog(@"%@", [formatter stringFromDate:date]); 
    [formatter release];
 

La principale différence ici est que vous devez vous adapter au fuseau horaire.

3voto

Nicolas Manzini Points 2205

Ou il y a ma méthode de classe. Il ne gère pas les années, mais cela pourrait facilement être ajouté, bien que ce soit mieux pour les petits timelaps comme les jours, heures et minutes. Il prend en compte les pluriels et ne montre que ce qui est nécessaire:

 +(NSString *)TimeRemainingUntilDate:(NSDate *)date {

    NSTimeInterval interval = [date timeIntervalSinceNow];
    NSString * timeRemaining = nil;

    if (interval > 0) {

        div_t d = div(interval, 86400);
        int day = d.quot;
        div_t h = div(d.rem, 3600);
        int hour = h.quot;
        div_t m = div(h.rem, 60);
        int min = m.quot;

        NSString * nbday = nil;
        if(day > 1)
            nbday = @"days";
        else if(day == 1)
            nbday = @"day";
        else
            nbday = @"";
        NSString * nbhour = nil;
        if(hour > 1)
            nbhour = @"hours";
        else if (hour == 1)
            nbhour = @"hour";
        else
            nbhour = @"";
        NSString * nbmin = nil;
        if(min > 1)
            nbmin = @"mins";
        else
            nbmin = @"min";

        timeRemaining = [NSString stringWithFormat:@"%@%@ %@%@ %@%@",day ? [NSNumber numberWithInt:day] : @"",nbday,hour ? [NSNumber numberWithInt:hour] : @"",nbhour,min ? [NSNumber numberWithInt:min] : @"00",nbmin];
    }
    else
        timeRemaining = @"Over";

    return timeRemaining;
}
 

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