Чтение и запись NSDate в базу данных sqlite через FMDatabase

У меня есть сомнения, можно ли NSDate напрямую хранить или читать из базы данных с помощью FMDatabase или нет.

Согласно моим исследованиям, FMDatabase считывает дату из записи, ожидая, что этот кортеж будет двойным значением. FMDatabase преобразует это двойное значение в дату следующим методом:

- (NSDate*) dateForColumn:(NSString*)columnName; {
    int columnIdx = [self columnIndexForName:columnName];

    if (columnIdx == -1) {
        return nil;
    }

    return [NSDate dateWithTimeIntervalSince1970:[self doubleForColumn:columnName]];
}

Основная проблема при таком подходе в том, что человеку, вручную вносящему данные в БД, будет сложно сделать так, чтобы FMDatabase понимал их в коде. Таким образом, кто-то не может просто ввести дату в двойном значении в графическом интерфейсе. Один из подходов заключается в использовании одной из этих функций.

date(timestring, modifier, modifier, ...)
time(timestring, modifier, modifier, ...)
datetime(timestring, modifier, modifier, ...)
julianday(timestring, modifier, modifier, ...)
strftime(format, timestring, modifier, modifier, ...)

Но накладные расходы здесь снова заключаются в том, чтобы каждый раз запускать запрос для ввода записи с помощью операции вставки, подобной этой:

Compute the current date.
SELECT date('now');

Compute the last day of the current month.
SELECT date('now','start of month','+1 month','-1 day');

Я хочу, чтобы дата сохранялась в базе данных в следующем формате:

TEXT as ISO8601 strings ("YYYY-MM-DD")

И сохраните его в формате даты в базе данных, чтобы я мог:

  1. Используйте средство сравнения дат в запросах.
  2. Сделайте FMDatabase понятным для чтения и записи в этом формате даты.

Есть ли какой-либо прямой способ взаимодействия FMDatabase с таким форматом даты? Или это ограничение FMDatabase, и мне придется расширить класс FMDatabase для обработки чтения и записи NSDate в формат даты sqlite?

Спасибо

Изменить: один из авторов/модераторов FMDatabase должен сказать это об этом: http://code.google.com/p/flycode/issues/detail?id=16#c1


person Raj Pawan Gumdal    schedule 28.12.2011    source источник


Ответы (1)


Дата чтения из базы данных в формате ГГГГ-ММ-ДД.

Я расширил класс FMResultSet, включив в него следующие дополнительные методы:

Файл FMResultSet+Addtion.h:

typedef enum
{
    eText,
    eReal,
    eInteger
}EDateAndTimeDataType;
// Reference: http://www.sqlite.org/datatype3.html

typedef enum
{
    eDateString    // YYYY-MM-DD format
    // Rest is un implemented
}EDateAndTimeFunctionType;
// Refernce: http://www.sqlite.org/lang_datefunc.html

@interface FMResultSet (Additions)

-(NSDate*)dateForColumn:(NSString *)columnName withDataType:(EDateAndTimeDataType)inDateDataType functionType:(EDateAndTimeFunctionType)inFunctionType;
-(NSDate*)dateForColumnIndex:(int)columnIdx withDataType:(EDateAndTimeDataType)inDateDataType functionType:(EDateAndTimeFunctionType)inFunctionType;

@end

Файл FMResultSet+Addition.m:

@implementation FMResultSet (Additions)

-(NSDate*)dateForColumn:(NSString *)columnName withDataType:(EDateAndTimeDataType)inDateDataType functionType:(EDateAndTimeFunctionType)inFunctionType
{
    return [self dateForColumnIndex:[self columnIndexForName:columnName]
                       withDataType:inDateDataType
                       functionType:inFunctionType];
}

-(NSDate*)dateForColumnIndex:(int)columnIdx withDataType:(EDateAndTimeDataType)inDateDataType functionType:(EDateAndTimeFunctionType)inFunctionType
{
    NSAssert (eText==inDateDataType, @"Only Text type is implemented for now");
    NSAssert (eDateString==inFunctionType, @"Only date() function type is implemented for now");

    NSDate *theDate = nil;
    NSString *dateString = [self stringForColumnIndex:columnIdx];
    if (nil!=dateString)
    {
        theDate = [Utility getDateFromString:dateString
                              withDateFormat:@"yyyy-MM-dd"];
        NSLog(@"Date from DB: %@", theDate);
    }
    return theDate;
}

@end

Полезность:

+(NSDate *)getDateFromString:(NSString *)inString withDateFormat:(NSString*)inDateFormat
{
    NSDate *date =nil;
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    [dateFormatter setDateFormat:inDateFormat];

    NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    [dateFormatter setLocale:enUSPOSIXLocale];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    [enUSPOSIXLocale release];

    date = [dateFormatter dateFromString:inString];
    [dateFormatter release];
    return date;
}

**Изменить: хотя это работает для таких запросов, как "выбрать * из table_name", оно не работает в запросах, сравнивающих даты. Нужны решения для этого.

person Raj Pawan Gumdal    schedule 29.12.2011