Como obter uma coluna datetime no SQLite com o Objective C

Como você obtém uma coluna datetime no SQLite com o Objective C?

Eu tenho uma tabela com 4 campos: pk , datetime , value1 e value2 . pk (chave primária), value1 e value2 são inteiros, então estou usando:

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

Mas o que devo usar para datetime ?

No SQLite, não existe um tipo de coluna de data / hora per se, então um acaba representando datas como valores de data julianos (colunas reais) ou em strings (colunas de texto). O SQLite também é muito específico em como as datas são representadas em strings, aaaa-MM-dd HH: mm: ss (somente).

Estes são alguns methods que escrevi para trabalhar com datas SQLite do Objective-C. Esses methods são implementados em uma categoria no NSDate.

Certifique-se de verificar a funcionalidade que o SQLite oferece para trabalhar com datas Julianas. Eu descobri que estes são bastante úteis ( http://www.sqlite.org/lang_datefunc.html ). Uma function para derivar julianDay de um NSDate é incluída no exemplo de código.

Parece que este assunto também foi abordado aqui. Datas persistentes para SQLite3 em um aplicativo do 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; } 

Se você puder definir o database, você também pode usar REAL (tipo de dados SQLite) como o tipo para o datetime e, em seguida, carregá-lo com sqlite3_column_double() . Isso retornará uma variável do tipo double .

Então você pode usar [NSDate dateWithTimeIntervalSince1970:double_value] para obter um object NSDate .

Observe que a solução de categoria acima tem um problema, pois está sujeita às configurações de localidade no dispositivo do usuário. Por exemplo, para a meia-noite de 5 de abril de 2010, o sqlLiteDateRepresentation acima retornaria 2010/04/05 00:00:00 para os computadores da maioria das pessoas, no entanto, encontrei um cenário em que as configurações de localidade de um usuário causaram a mesma function “2010/04/05 12:00:00 am “que quando usado na minha consulta não retorna nenhuma linha. Isso parece seguir a documentação do NSDateFormatter: “Em geral, você é encorajado a usar estilos de formato (consulte timeStyle, dateStyle e NSDateFormatterStyle) em vez de usar strings de formato personalizado, pois o formato de um determinado estilo reflete as preferências do usuário. estilos também refletem a configuração local. ” Embora eu não vi uma boa maneira de usar o timeStyle / dateStyle para obter o mesmo formato que aaaa / MM / dd HH: mm: ss que SQLite parece precisar. Temo que sua melhor aposta seja provavelmente uma solução personalizada na qual você garante que a hora seja escrita definitivamente no formato 24H, não permita que as configurações do local causem bugs.

Se você quiser apenas obter um NSDate de um campo de data e hora do SQLite, onde dateTime é o campo retornado do database:

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

Agora trabalha!

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