2009-08-05 5 views
8

He estado tratando de encontrar una forma sensata de almacenar datos diarios usando Core Data en el iPhone.Cómo almacenar fechas sin tiempos en Core Data

Mi aplicación recibe datos en formato CSV, con una fecha pero no hay tiempo:

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

Cuando se almacena estos datos, sólo debe haber un registro por día. Pensé que lo mejor que podía hacer era crear un NSDate para almacenar, pero eliminar los datos de la zona horaria &.

Puedo crear fácilmente un NSDate sin horas, minutos o segundos usando NSDateComponents o NSDateFormatter. Sin embargo, incluso cuando me puse la zona horaria de forma explícita a UTC o en cero segundos de GMT, la salida de una fecha creada con NSLog() siempre tiene mi zona horaria local, como:

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

¿Alguien sabe de una mejor manera de hacer NSDates sin componentes de tiempo? ¿O tal vez una mejor forma de almacenar las fechas?

Respuesta

9

Una buena regla de programación es almacenar siempre las fechas en UTC. No importa si usa Core Data o no; aún tendrás que trabajar porque las clases de Apple son una mierda.

fechas se representan internamente como un número de segundos transcurridos desde una fecha de referencia que es, creo, 1º de enero de 2001 00:00:00 (aunque la fecha de referencia actual no es muy importante). El punto es, NSDate los objetos siempre se muestran de forma nativa en UTC. Si la fecha que está recibiendo en su archivo CSV son locales, tendrá que hacer algo como esto para obtener la hora UTC:

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

Entonces, me puse el tiempo de 00:00:00 . Ahora está guardando la fecha, a la medianoche, en UTC. Para fines de presentación, usará un NSDateFormatter configurado con la zona horaria de su elección (la zona horaria del sistema es la predeterminada si no especifica uno) para visualizar esas fechas.

Las zonas horarias en realidad no importa cuando estás tratar con fechas, sin embargo. Siempre que se asegure de configurar la zona horaria en su NSDateFormatter en UTC, siempre mostrará la misma fecha, sin importar la zona horaria que el usuario haya seleccionado en su dispositivo.

Si no te gusta esta solución, siempre puedes guardar tus fechas en un formato alternativo. Puede usar un double o int para almacenar la fecha en algún formato personalizado (p.el número de días desde alguna fecha de referencia), o incluso puede rodar su propia clase para modelar la fecha exactamente de la manera que desee y almacenarla como un objeto NSData. Mientras implementa NSCoding la clase, puede serializar a un objeto NSData de datos básicos. Solo necesita establecer el tipo de atributo en Datos principales en "Transformable".

Tiene un montón de opciones aquí, y ninguna implica el esfuerzo de escribir sus propias consultas y bases de datos SQLite.

+1

Muchas gracias. Lo tengo ordenado ahora. Su respuesta hace que las conversiones tengan más sentido y Peter Hosey's below explica la salida NSLog. – Ben

2

El objeto NSDate siempre incorporará fecha de tiempo, para citar los documentos que "representan [s] un único punto en el tiempo" y lo hace almacenando un valor temporal desde su fecha de referencia (inicio del 1 de enero de 2001 a GMT , de nuevo de acuerdo con los documentos). Por lo tanto, no puede tener un NSDate que no tenga conocimiento de la hora del día.

En lugar de intentar almacenar las fechas a su manera, seguiría utilizando NSDate en su modelo y consideraría agregar un par de métodos a su clase de entidad, uno de los cuales hará lo que describió anteriormente, configurando NSDate en 00: 00:00 en un día determinado. El otro podría devolver solo la fecha de un NSDate en su formato preferido. Estos usarían el eliminador y el setter generados por Core Data para acceder a la propiedad NSDate.

Al seguir usando NSDate, está utilizando una clase con la que Core Data puede trabajar de forma nativa, lo que significa que aún puede usar predicados fácilmente para filtrar u ordenar los resultados por fecha sin tener que pensar demasiado al respecto.

+0

Gracias por la respuesta. Esto todavía deja el problema de las zonas horarias. Por ejemplo: guardo mis datos en julio en Londres (GMT + 0100) y otra persona los guarda en Cupertino (GMT-0700). Ahora hay una diferencia de 8 horas en la fecha almacenada. Creo que probablemente sea más eficiente simplemente regresar a SQLite sin formato. – Ben

+0

Estoy totalmente no entienden el problema: la fecha en un NSDate se almacena como una fecha absoluta, segundos desde 1/1/2001 00:00:00 GMT * *. Entonces, si dos personas en diferentes zonas horarias almacenan la fecha 'actual' exactamente en el mismo instante, sus NSDate son idénticas. La zona horaria solo funciona en la recuperación/visualización, y a menos que le indique a NSDate lo contrario, irá con la zona horaria de la configuración regional del sistema. En otras palabras, si sus dos conjuntos de datos se almacenan en el mismo momento en Londres y Cupertino, las fechas almacenadas son las mismas, sin diferencias. – marramgrass

3

Un NSDate no tiene zona horaria. NSLog usa su zona horaria local; dice +0100 porque ahí es donde estás.

+0

Gracias. No sabía que era NSLog usando la zona horaria local. Después de señalar esto, jugué un poco más con la fecha y hora del sistema y ahora tiene mucho más sentido. – Ben

+0

No entendí el +0100. ¿Qué es exactamente lo que representa? –

+0

srikanth rongali: desplazamiento de la zona horaria. El cuestionario fue una hora antes de GMT: GMT + 0100. (El último par de dígitos son minutos, por lo que una zona horaria cinco horas y media por delante de GMT sería +0530). –