Wie breche ich einen NSTimeInterval in Jahr, Monate später, Tage, Stunden, Minuten und Sekunden auf dem iPhone?

StackOverflow https://stackoverflow.com/questions/1237778

Frage

Ich habe ein Zeitintervall, das Jahr erstreckt, und ich möchte alle Zeitkomponenten von Jahr bis auf Sekunden.

Mein erster Gedanke ist das Zeitintervall von Sekunden in einem Jahr auf ganzzahlige teilen, subtrahiert, dass aus einer laufenden Summe von Sekunden, Kluft, die durch Sekunden in einem Monat, subtrahiert, dass aus der laufenden Summe und so weiter.

Das nur verworren scheint und ich habe gelesen, dass, wenn Sie etwas tun, die gewundene aussieht, gibt es wahrscheinlich eine integrierte Methode.

Gibt es?

I integriert Alex 2. Methode in meinem Code.

Es ist in einem Verfahren nach einem UIDatePicker in meiner Schnittstelle genannt.

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);

Wenn ich die Datumsauswahl auf ein Datum 1 Jahr und 1 Tag in der Vergangenheit, die ich erhalte:

  

1 Jahr 1 Monat 1 Tag 16 Stunden 0   Minuten 20 Sekunden

die 1 Monat und 16 Stunden ab. Wenn ich die Datumsauswahl bis zu 1 Tag in der Vergangenheit, bin ich um den gleichen Betrag aus.

Aktualisieren : Ich habe eine Anwendung, die Ihr Alter in Jahren berechnet, da Sie Ihren Geburtstag (Satz von einem UIDatePicker), aber es war oft weg. Dies beweist, gibt es eine Ungenauigkeit, aber ich kann nicht herausfinden, woher es kommt, kann Sie?

War es hilfreich?

Lösung

Kurzbeschreibung

  1. Nur einen anderen Ansatz, die Antwort von JBRWilkinson zu vervollständigen, aber einige Code hinzufügen. Es kann bietet auch eine Lösung für Alex Reynolds Kommentar.

  2. Mit NSCalendar Methode:

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

    • „Returns, als NSDateComponents Objekt angegebenen Komponenten, die Differenz zwischen beiden mitgelieferten Daten“. (Aus der API-Dokumentation).

  3. Erstellen 2 NSDate, deren Differenz die NSTimeInterval Sie wollen brechen. (Wenn Ihr NSTimeInterval kommt aus dem Vergleich 2 NSDate brauchen Sie nicht, diesen Schritt zu tun, und Sie brauchen noch nicht einmal die NSTimeInterval, gelten nur die Daten an die NSCalendar Methode).

  4. Erhalten Sie Ihre Zitate aus NSDateComponents

Beispielcode

// 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
NSCalendarUnit unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;

NSDateComponents *breakdownInfo = [sysCalendar components:unitFlags fromDate:date1  toDate:date2  options:0];
NSLog(@"Break down: %i min : %i hours : %i days : %i months", [breakdownInfo minute], [breakdownInfo hour], [breakdownInfo day], [breakdownInfo month]);

Andere Tipps

Dieser Code ist sich bewusst, Tageslichtsparzeiten und andere mögliche unangenehme Dinge.

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

Konvertieren Sie Ihr Intervall in eine NSDate +dateWithIntervalSince1970 verwenden, aus den aktuellen Komponenten erhalten jenen mit NSCalendar des -componentsFromDate Methode.

SDK Referenz

Von iOS8 und oben können Sie NSDateComponentsFormatter verwenden

Es hat Methoden Zeitdifferenz in benutzerfreundlich formatiert String.

konvertieren
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;

NSLog(@"%@", [formatter stringFromTimeInterval:1623452]);

Das gibt den Ausgang - 2 Wochen, 4 Tage, 18 Stunden, 57 Minuten, 32 Sekunden

Dies funktioniert für mich:

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

Der Hauptunterschied ist, dass Sie für die Zeitzone anpassen müssen.

Oder es ist meine Klassenmethode. Es behandelt nicht Jahre, aber das leicht addedn werden konnte, obwohl es besser ist, für kleine Timelaps wie Tage, Stunden und Minuten. Es dauert Plurale berücksichtigt und nur zeigt, was gebraucht wird:

+(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;
}
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];

// format: YYYY-MM-DD HH:MM:SS ±HHMM
NSString *dateStr = [date description];
NSRange range;

// year
range.location = 0;
range.length = 4;
NSString *yearStr = [dateStr substringWithRange:range];
int year = [yearStr intValue] - 1970;

// month
range.location = 5;
range.length = 2;
NSString *monthStr = [dateStr substringWithRange:range];
int month = [monthStr intValue];

// day, etc.
...
- (NSString *)convertTimeFromSeconds:(NSString *)seconds {

    // Return variable.
    NSString *result = @"";

    // Int variables for calculation.
    int secs = [seconds intValue];
    int tempHour    = 0;
    int tempMinute  = 0;
    int tempSecond  = 0;

    NSString *hour      = @"";
    NSString *minute    = @"";
    NSString *second    = @"";

    // Convert the seconds to hours, minutes and seconds.
    tempHour    = secs / 3600;
    tempMinute  = secs / 60 - tempHour * 60;
    tempSecond  = secs - (tempHour * 3600 + tempMinute * 60);

    hour    = [[NSNumber numberWithInt:tempHour] stringValue];
    minute  = [[NSNumber numberWithInt:tempMinute] stringValue];
    second  = [[NSNumber numberWithInt:tempSecond] stringValue];

    // Make time look like 00:00:00 and not 0:0:0
    if (tempHour < 10) {
        hour = [@"0" stringByAppendingString:hour];
    } 

    if (tempMinute < 10) {
        minute = [@"0" stringByAppendingString:minute];
    }

    if (tempSecond < 10) {
        second = [@"0" stringByAppendingString:second];
    }

    if (tempHour == 0) {

        NSLog(@"Result of Time Conversion: %@:%@", minute, second);
        result = [NSString stringWithFormat:@"%@:%@", minute, second];

    } else {

        NSLog(@"Result of Time Conversion: %@:%@:%@", hour, minute, second); 
        result = [NSString stringWithFormat:@"%@:%@:%@",hour, minute, second];

    }

    return result;

}

Hier ist eine andere Möglichkeit, etwas sauberer:

NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSString *dateStr = [date description];
const char *dateStrPtr = [dateStr UTF8String];

// format: YYYY-MM-DD HH:MM:SS ±HHMM
int year, month, day, hour, minutes, seconds;
sscanf(dateStrPtr, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minutes, &seconds);
year -= 1970;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top