Cómo obtener una columna de fecha y hora en SQLite con Objective C

¿Cómo se obtiene una columna de fecha y hora en SQLite con Objective C?

Tengo una tabla con 4 campos: pk , datetime , value1 y value2 . pk (clave principal), value1 y value2 son enteros, entonces estoy usando:

  int value1 = sqlite3_column_int(statement, 2); int value1 = sqlite3_column_int(statement, 3); 

Pero, ¿qué debería usar para datetime ?

En SQLite, no hay un tipo de columna de fecha / hora per se, por lo que uno termina representando fechas ya sea como valores de fecha juliana (columnas reales) o en cadenas (columnas de texto). SQLite también es muy particular en cómo las fechas se representan en cadenas, aaaa-MM-dd HH: mm: ss (solo).

Estos son algunos métodos que escribí para trabajar con fechas de SQLite de Objective-C. Estos métodos se implementan en una categoría en NSDate.

Asegúrese de verificar la funcionalidad que ofrece SQLite para trabajar con fechas Julian. He encontrado que estos son bastante útiles ( http://www.sqlite.org/lang_datefunc.html ). En el ejemplo de código se incluye una función para derivar un julianDay de NSDate.

Parece que este tema también fue cubierto aquí. Fechas persistentes para SQLite3 en una aplicación de iPhone

 + (NSDate *) dateWithSQLiteRepresentation: (NSString *) myString; { NSAssert3(myString, @"%s: %d; %s; Invalid argument. myString == nil", __FILE__, __LINE__, __PRETTY_FUNCTION__); return [[self sqlLiteDateFormatter] dateFromString: myString]; } + (NSDate *) dateWithSQLiteRepresentation: (NSString *) myString timeZone: (NSString *) myTimeZone; { NSString * dateWithTimezone = nil; NSDate * result = nil; NSAssert3(myString, @"%s: %d; %s; Invalid argument. myString == nil", __FILE__, __LINE__, __PRETTY_FUNCTION__); NSAssert3(myTimeZone, @"%s: %d; %s; Invalid argument. myTimeZone == nil", __FILE__, __LINE__, __PRETTY_FUNCTION__); dateWithTimezone = [[NSString alloc] initWithFormat: @"%@ %@", myString, myTimeZone]; result = [[self sqlLiteDateFormatterWithTimezone] dateFromString: dateWithTimezone]; [dateWithTimezone release]; return result; } + (NSString *) sqlLiteDateFormat; { return @"yyyy-MM-dd HH:mm:ss"; } + (NSString *) sqlLiteDateFormatWithTimeZone; { static NSString * result = nil; if (!result) { result = [[NSString alloc] initWithFormat: @"%@ zzz", [self sqlLiteDateFormat]]; } return result; } + (NSDateFormatter *) sqlLiteDateFormatter; { static NSDateFormatter * _result = nil; if (!_result) { _result = [[NSDateFormatter alloc] init]; [_result setDateFormat: [self sqlLiteDateFormat]]; } return _result; } + (NSDateFormatter *) sqlLiteDateFormatterWithTimezone; { static NSDateFormatter * _result = nil; if (!_result) { _result = [[NSDateFormatter alloc] init]; [_result setDateFormat: [self sqlLiteDateFormatWithTimeZone]]; } return _result; } - (NSString *) sqlLiteDateRepresentation; { NSString * result = nil; result = [[NSDate sqlLiteDateFormatter] stringFromDate: self]; return result; } - (NSTimeInterval) unixTime; { NSTimeInterval result = [self timeIntervalSince1970]; return result; } #define SECONDS_PER_DAY 86400 #define JULIAN_DAY_OF_ZERO_UNIX_TIME 2440587.5 - (NSTimeInterval) julianDay; { return [self unixTime]/SECONDS_PER_DAY + JULIAN_DAY_OF_ZERO_UNIX_TIME; } + (NSDate *) dateWithJulianDay: (NSTimeInterval) myTimeInterval { NSDate *result = [self dateWithTimeIntervalSince1970: (myTimeInterval - JULIAN_DAY_OF_ZERO_UNIX_TIME) * SECONDS_PER_DAY]; return result; } 

Si puede definir la base de datos, también podría usar REAL (tipo de datos SQLite) como el tipo de fecha y hora, y luego cargarlo con sqlite3_column_double() . Esto devolverá una variable del tipo double .

Luego puede usar [NSDate dateWithTimeIntervalSince1970:double_value] para obtener un objeto NSDate .

Tenga en cuenta que la solución de categoría anterior tiene un problema porque está sujeta a la configuración regional en el dispositivo del usuario. Por ejemplo, para la medianoche del 5 de abril de 2010, sqlLiteDateRepresentation anterior devolverá 2010/04/05 00:00:00 para las máquinas de la mayoría de las personas; sin embargo, me encontré con un escenario en el que las configuraciones locales de un usuario provocaron la misma función para producir “2010/04/05 12:00:00 a.m. “que cuando se utiliza en mi consulta no devuelve ninguna fila. Esto parece seguir de la documentación de NSDateFormatter: “En general, se recomienda utilizar estilos de formato (vea timeStyle, dateStyle y NSDateFormatterStyle) en lugar de usar cadenas de formato personalizadas, ya que el formato de un estilo determinado refleja las preferencias de un usuario. los estilos también reflejan la configuración regional “. Aunque no vi una buena manera de utilizar timeStyle / dateStyle para obtener el mismo formato que aaaa / MM / dd HH: mm: ss que SQLite parece necesitar. Me temo que su mejor opción es una solución personalizada en la que se asegure de que la hora esté definitivamente escrita en formato 24H, no permita que la configuración regional cause errores.

Si solo desea obtener un NSDate de un campo de fecha y hora de SQLite, donde dateTime es el campo devuelto desde la base de datos:

 NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSDate *date = [dateFormatter dateFromString:dateTime]; 

¡Ahora trabaja!

 NSString *dateValueS = [[NSString alloc] initWithUTF8String:(char*) sqlite3_column_text(statement,2)];