Frage

Grüße,

Vor kurzem stand ich vor ein großes Problem (wie es mir scheint) mit NSCalendar Klasse.

In meiner Aufgabe muss ich arbeiten mit einer großen Zeiträumen von 4000BC zu 2000AD (Gregorianischer Kalender) zu starten. In einem Ort war ich gezwungen, einige NSDate 100 Jahres-Intervall zu erhöhen. Bei Erhöhen der Jahre in AD Timeline. (0 -> ...) alles funktionierte gut, aber wenn ich die gleiche Sache mit BC probierten, war ich ein wenig verwirrt

Das Problem ist, wenn Sie versuchen, 100 Jahre zu 3000BC hinzufügen [bearbeitet] Jahr, erhalten Sie 3100BC [bearbeitet] egal was ... ich persönlich fand es seltsam und unlogisch. Das richtige Ergebnis sollte 2900BC sein.

Hier ist das Codebeispiel für Sie das „nicht richtig“ Verhalten zu sehen:

NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];

// initing
NSDateComponents *comps = [[[NSDateComponents alloc] init] autorelease];
[comps setYear:-1000];
NSDate *date = [gregorian dateFromComponents:comps];

// math
NSDateComponents *deltaComps = [[[NSDateComponents alloc] init] autorelease];
[deltaComps setYear:100];

date = [gregorian dateByAddingComponents:deltaComps toDate:date options:0];

// output
NSString *dateFormat = @"yyyy GG";

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:dateFormat];
NSLog(@"%@", [formatter stringFromDate:date]);

Was kann sagen Sie zu diesem Verhalten? Ist dies, wie es funktionieren soll oder ist das ein Fehler? Ich bin verwirrt. S

BTW .: das Verfahren [NSCalendar Komponenten: VonDatum: toDate: Optionen:] erlauben uns nicht, den Unterschied zwischen den Jahren in BC-Ära zu berechnen ... zusätzliche ‚WARUM?‘ in dieser Büchse der Pandora.

P. S .: Ich wurde durch offizielle Dokumentation zu graben und andere Ressourcen, aber nichts gefunden in Bezug auf dieses Problem (oder vielleicht ist es beabsichtigt, an der Arbeit so und ich bin ein Idiot?).

War es hilfreich?

Lösung

fand ich eine einfache Abhilfe für diesen Fehler. Hier ist sie:

@interface NSCalendar (EraFixes)

- (NSDate *)dateByAddingComponentsRegardingEra:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts;

@end

@implementation NSCalendar (EraFixes)

- (NSDate *)dateByAddingComponentsRegardingEra:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts
{
    NSDateComponents *toDateComps = [self components:NSEraCalendarUnit fromDate:date];
    NSDateComponents *compsCopy = [[comps copy] autorelease];

    if ([toDateComps era] == 0) //B.C. era
    {
        if ([comps year] != NSUndefinedDateComponent) [compsCopy setYear:-[comps year]];
    }

    return [self dateByAddingComponents:compsCopy toDate:date options:opts];
}

@end

Wenn Sie sich fragen, warum ich umkehren nur Jahre, die Antwort ist einfach, jede andere Komponente außer Jahren Erhöhen und Erniedrigen in der richtigen Weise (ich habe sie nicht alle getestet, aber Monate und Tage scheinen zu funktionieren).

Bearbeiten :. Entfernt fälschlicherweise hinzugefügt Autorelease, dank John

Andere Tipps

Es ist ein Fehler und oder ein Feature. Der Apple doc nie sagt, was sie von bedeutet das Hinzufügen von Komponenten zum kalendarischen Datum . Es ist völlig kostenlos für sie zu definieren, um die BCE date „Hinzufügen einer Komponente“, wie nur die Zugabe zum Jahr Komponente.

Ja, ich stimme mit Ihnen überein, dass es nicht eingängig und ich denke, dass es ein Fehler ist.

Sie benötigen NSDate auf beiden

konvertieren
  • die zweite von der UNIX-Epoche (1.1.1970) mit -timeIntervalSince1970
  • die zweite von der OS X Epoche (1.1.2001) mit -timeIntervalSinceReferenceDate

Sie können dann die Berechnung durchführen, und wandelt es in ein NSDate zurück. Ich denke, es ist eine schlechte Idee, Arbeit im gregorianischen Kalender die ganze Zeit ... Es wäre besser, in dem gregorianischen Kalender zu konvertieren, bevor Sie es auf der GUI angezeigt.

Stellen Sie sich vor, dass Sie Datum mit ersten Moment unserer Zeit haben - AD 0001-01-01 00.00.00 Was war vor der Zeit.? BC 0001-01-01 00.00.01 . Wenn Cocoa-Entwickler grundlegende Arithmetik für diese Aufgabe verwendet, würden Sie bekommen AD 0000-12-31 23.59.59 . Ist das sinnvoll für gregorianischen Kalender? Ich denke nicht. So scheint es mir, dass der bequemste Weg, Kalender zu implementieren war Era Flag zu verwenden, und ändern „ Zeitrichtung “, wenn sie mit BC-Ära zu tun für Menschen lesbarer Daten in jedem Fall zu erhalten.

BTW .: [NSCalendar dateByAddingComponents:toDate:options:] wirklich seltsam verhält und sich nicht Zeitintervall zwischen BC Daten zählen, überprüfte ich auch. Also, für BC Termine können Sie verwenden Problem zu umgehen, zum Beispiel Nach den Daten, um AD zu übersetzen und dann diff zu finden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top