2010-12-01 10 views
8

Ich schreibe eine App, die Core-Daten verwendet, um meine Daten zu speichern. Darin enthalten ist ein Datumsfeld, von dem ich nur das Datum und nicht die Uhrzeit interessiert bin. Ich brauche Datensätze auszuwählen, basierend auf dem Datum (keine Zeit) und so habe ich eine Kategorie NSDate erstellt Zeit, um ein Datum zurückzubringen, normiert auf einen Satz wie folgt:NSDate Best Practice beim Erstellen eines Datums ohne Zeitelement

+ (NSDate *)dateWithNoTime:(NSDate *)dateTime { 
if(dateTime == nil) { 
    dateTime = [NSDate date]; 
} 
NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:dateTime]; 
NSDate *dateOnly = [[NSCalendar currentCalendar] dateFromComponents:comps]; 
[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];   // Push to Middle of day. 
return dateOnly; 

}

ich dann Verwenden Sie das, wenn ich dem Core-Datenspeicher Daten hinzufüge (ich habe einen Setter, der diese Methode verwendet, um den primitiven Datumswert festzulegen) und dann verwende ich diese Methode, um ein Datum zu erstellen, mit dem ich die Daten beim Ausführen einer Abrufanforderung vergleiche . In der Theorie sollte das immer funktionieren - also die Daten heraussuchen, nach denen ich suche.

Ich bin etwas nervös, aber ich bin mir nicht ganz sicher, welchen Effekt das Ändern der Zeitzone oder des Gebiets hat. Wird es noch funktionieren?

Was gilt als Best Practice beim Speichern und Suchen eines Datums nur, wenn Sie nicht an der Uhrzeit interessiert sind.

Prost.

EDIT

Nach der Diskussion Lesen empfohlen Ich denke, dass ich meinen Code wie folgt ändern sollte. Der Gedanke ist, dass, wenn ich sicherstelle, dass ich es an ein bestimmtes Kalendersystem und eine bestimmte Zeitzone (UTC) verschiebe, die Daten immer gleich sein sollten, egal wo du bist, wenn du das Datum einstellst und das Datum liest. Alle Kommentare zu diesem neuen Code werden geschätzt.

+ (NSDate *)dateWithNoTime:(NSDate *)dateTime { 
if(dateTime == nil) { 
    dateTime = [NSDate date]; 
} 

NSCalendar  *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; 
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; 
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease]; 
components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit 
         fromDate:dateTime]; 

NSDate *dateOnly = [calendar dateFromComponents:components]; 

[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];   // Push to Middle of day. 
return dateOnly; 

}

+0

Danke für die Lösung !! : D Nur eine kleine Korrektur: Die Linie: '[dateOnly dateByAddingTimeInterval: (60,0 * 60,0 * 12,0)];' Sollte sein: 'dateOnly = [dateOnly dateByAddingTimeInterval: (60,0 * 60,0 * 12,0)];' –

Antwort

5

Sie haben ein paar Probleme mit der hier beschäftigen. Zuerst, wie Sie notiert haben, Zeitzonen. Sie müssen sich auch Gedanken über die Sommerzeit machen, die das Konzept von "Mittag" ändern.

Werfen Sie einen Blick auf CocoaDev this discussion, wo ein Apple Engineer gibt einige Antworten und diskutiert einige Best Practices.

+0

Danke dafür. Nach dem Lesen dieser Diskussion scheint es, dass ich sicherstellen sollte, dass ich immer dasselbe Kalendersystem und dieselbe Zeitzone zum Speichern und Vergleichen verwende. Ich habe einen neuen Code zu meiner Frage hinzugefügt, basierend auf diesem neuen Denken. – SimonB

3

Eine einfachere Lösung besteht darin, ein Prädikat zu verwenden, das nach Daten innerhalb eines bestimmten Bereichs sucht.

Verwenden Sie NSCalendarComponent, um ein Startdatum und ein Enddatum für Ihren "Tag" zu erstellen, und fügen Sie diese dann in das Prädikat ein.

NSPredicate *p=[NSPredicate predicateWithFormat:@"[email protected] <= date <= [email protected]",startDate,endDate]; 

Das wird die maximale Flexibilität ohne zu viel Komplexität bieten. Die Programmierung von Datum und Uhrzeit ist täuschend komplex. Sei bereit, etwas zu arbeiten.

2

Ich landete auch in einem Szenario, in dem ich eine NSDate haben musste, um ein Datum ohne Berücksichtigung der Zeit zu vergleichen.

Ich habe einen Filter mechanism und als Teil der Benutzeroberfläche, wenn der Benutzer wählte heute das Mindestdatum als Startdatum und das Enddatum wie heute würde ich "Alle Zeiträume" im Gegensatz zu einer Zeichenfolge im Format anzeigen :

1/5/2006 - 24/12/2009

Also brauchte ich mit +date von NSDate heutigen Datum zu nehmen, und es bis zum Ende Datum vergleichen. Dieses Enddatum kam von einem UIDatePicker ohne Zeit gesetzt, aber +date gab das Datum und die Uhrzeit von jetzt zurück.

Also schrieb ich diese kurze praktische Methode, sie erhält ein Datum Objekt verwendet NSDateComponents und die NSCalendar Klasse den Tag, Monat und Jahr zu extrahieren.

Diese drei Parameter werden dann eine neue NSDate mit NSDateFormatter's erstellen - dateFromString: Methode, ist das Ergebnis ein NSDate zum selben „Datum“ (in dem traditionellen menschlichen Konzept) entsprechend als Parameter date aber ohne Zeit.

- (NSDate *)strictDateFromDate:(NSDate *)date{ 
    NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; 
    NSDateComponents *components = [[NSCalendar currentCalendar] components:flags 
                    fromDate:[NSDate date]]; 
    NSString *stringDate = [NSString stringWithFormat:@"%d/%d/%d", components.day, components.month, components.year]; 

    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; 
    formatter.dateFormat = @"dd/MM/yyyy"; 

    return [formatter dateFromString:stringDate]; 
} 

Ich hoffe, dass Sie diese Funktion in Zukunft nutzen und genießen können.

+0

habe ich versucht, aber auch die Rückgabewerte enthält Zeitstempel !!! –