2009-08-05 5 views
8

Ich habe versucht, eine sinnvolle Möglichkeit zum Speichern von täglichen Daten mit Core Data auf dem iPhone zu finden.So speichern Sie Daten ohne Zeiten in Core Data

Meine app empfängt Daten im CSV-Format, mit einem Datum, aber keine Zeit:

date, cycles 
2009-08-01, 123 
2009-08-02, 234 
2009-08-03, 345 
2009-08-04, 456 

Wenn diese Daten gespeichert sind, gibt es nur einen Datensatz pro Tag sein sollte. Ich dachte, das beste, was zu tun ist, war ein NSDate zu erstellen, um gespeichert zu werden, aber streichen Sie die Zeit & Zeitzone Daten.

Ich kann einfach erstellen ein NSDate ohne Stunden, Minuten oder Sekunden mit NSDateComponents oder NSDateFormatter. Doch selbst wenn stelle ich die Zeitzone explizit auf UTC oder auf Null Sekunden von GMT, ein erstelltes Datum mit NSLog Ausgeben() immer hat meine lokale Zeitzone wie:

2009-07-29 00:00:00 +0100 

Hat jemand einen besseren Weg kennen NSDates ohne Zeitkomponenten machen? Oder vielleicht eine bessere Möglichkeit, die Daten zu speichern?

Antwort

9

Eine gute Programmierregel ist, Daten immer in UTC zu speichern. Es spielt keine Rolle, ob Sie Core Data verwenden oder nicht. Sie müssen immer noch etwas arbeiten, weil Apples Terminklassen ziemlich schlecht sind.

Daten werden intern als Anzahl von Sekunden seit einem Referenzdatum dargestellt, das, glaube ich, 1. Januar 2001 00:00:00 ist (obwohl das tatsächliche Referenzdatum nicht sehr wichtig ist). Punkt ist, NSDate Objekte sind immer nativ in UTC. Wenn die Daten die Sie in Ihrer CSV-Datei immer lokal sind, müssen Sie so etwas tun, um die UTC-Zeit zu bekommen:

NSDate *UTCDate = [localDate addTimeInterval:-[[NSTimeZone localTimeZone] secondsFromGMT]]; 

Dann habe ich die Zeit auf 00:00:00 gesetzt würde . Jetzt speichern Sie das Datum um Mitternacht in UTC. Zu Präsentationszwecken verwenden Sie eine NSDateFormatter, die mit der Zeitzone Ihrer Wahl konfiguriert ist (die Systemzeitzone ist die Standardeinstellung, wenn Sie keine angeben), um diese Daten anzuzeigen.

Zeitzonen sind nicht wirklich wichtig, wenn Sie nur mit Daten zu tun haben. Solange Sie sicherstellen, dass die Zeitzone auf NSDateFormatter auf UTC eingestellt ist, wird immer das gleiche Datum angezeigt, unabhängig davon, welche Zeitzone der Benutzer auf seinem Gerät ausgewählt hat.

Wenn Ihnen diese Lösung nicht gefällt, können Sie Ihre Daten immer in einem anderen Format speichern. Sie können eine double oder int verwenden, um das Datum in einem benutzerdefinierten Format zu speichern (z.die Anzahl der Tage seit einem Referenzdatum), oder Sie können sogar Ihre eigene Klasse rollen, um das Datum genau nach Ihren Wünschen zu modellieren und als NSData Objekt zu speichern. Solange die Klasse NSCoding implementiert, können Sie sie zu einem NSData Objekt in Core Data serialisieren. Sie müssen nur den Attributtyp in Core Data auf "Transformable" setzen.

Sie haben eine Menge Optionen hier, und keiner von ihnen beinhaltet den Aufwand des Schreibens Ihrer eigenen SQLite Abfragen und Datenbanken.

+1

Vielen Dank. Ich habe es jetzt sortiert. Ihre Antwort macht die Umwandlungen sinnvoller und Peter Hosey erklärt unten die NSLog-Ausgabe. – Ben

2

Das NSDate-Objekt wird immer das Zeitdatum enthalten - um die Dokumente zu zitieren, stellt es einen einzigen Zeitpunkt dar und speichert einen Zeitwert seit dem Referenzdatum (Beginn des 1. Januar 2001 bei GMT) , wieder nach den Dokumenten). Daher können Sie kein NSDate haben, das die Uhrzeit nicht kennt.

Anstatt Daten auf Ihre eigene Art zu speichern und zu speichern, würde ich immer noch NSDate in Ihrem Modell verwenden und ein paar Methoden zu Ihrer Entitätsklasse hinzufügen, von denen eine das oben beschriebene tut und NSDate auf 00 setzt: 00:00 an einem bestimmten Tag. Der andere könnte nur das Datum von einem NSDate in Ihrem bevorzugten Format zurückgeben. Diese verwenden dann das von Core Data generierte Getter und Setter, um auf die NSDate-Eigenschaft zuzugreifen.

Durch die Verwendung von NSDate verwenden Sie eine Klasse, mit der Core Data nativ arbeiten kann, dh Sie können Prädikate immer noch problemlos zum Filtern verwenden oder die abgerufenen Ergebnisse nach Datum sortieren, ohne darüber nachzudenken.

+0

Danke für die Antwort. Dies hinterlässt immer noch das Problem der Zeitzonen. Zum Beispiel: Ich speichere meine Daten im Juli London (GMT + 0100) und jemand anderes speichert sie in Cupertino (GMT-0700). Es gibt jetzt einen Unterschied von 8 Stunden im gespeicherten Datum. Ich denke, es ist wahrscheinlich effizienter, einfach auf SQLite zurückzugreifen. – Ben

+0

Ich verstehe das Problem nicht ganz: Das Datum in einem NSDate wird als absolutes Datum gespeichert, Sekunden seit 00:00:00 1/1/2001 * GMT *. Wenn also zwei Personen in unterschiedlichen Zeitzonen das "aktuelle" Datum genau zum selben Zeitpunkt speichern, sind ihre NSDates identisch. Die Zeitzone wird nur beim Abrufen/Anzeigen verwendet, und wenn Sie NSDate nichts mitteilen, wird es mit der Zeitzone des Systemgebiets synchronisiert. Mit anderen Worten, wenn Ihre zwei Datensätze in London und Cupertino gleichzeitig gespeichert werden, sind die gespeicherten Daten gleich, ohne Unterschied. – marramgrass

3

Ein NSDate hat keine Zeitzone. NSLog verwendet Ihre lokale Zeitzone; Es sagt +0100, weil du da bist.

+0

Danke. Mir war nicht bewusst, dass NSLog die lokale Zeitzone verwendet. Nachdem Sie darauf hingewiesen haben, habe ich mit den System Datum & Zeit Einstellungen mehr gespielt und es macht jetzt viel mehr Sinn. – Ben

+0

Ich habe die +0100 nicht verstanden. Was repräsentiert es genau? –

+0

srikanth rongali: Zeitzonen-Offset. Der Fragesteller war eine Stunde vor GMT: GMT + 0100. (Das letzte Zahlenpaar ist Minuten, also wäre eine Zeitzone fünfeinhalb Stunden vor GMT + 0530.) –