Использование NSPredicate для получения точного NSDate из NSManagedObjectContect

Я пытаюсь получить результаты моего объекта «MeterReading», который имеет два свойства: «отметка времени» и «чтение». "отметка времени" - это NSDate. Сейчас я пытаюсь получить объект с точной датой.

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MeterReading" inManagedObjectContext:context];
[request setEntity:entity];
NSLog(@"%f", [self.timestamp timeIntervalSince1970]);

NSPredicate *pre = [NSPredicate predicateWithFormat:@"timestamp == %@", self.timestamp];
NSLog(@"%@", pre);
[request setPredicate:pre];

Теперь self.timestamp заранее передается другому ViewController, NSLog показывает:

1290264372.210091

Журналы NSPredicate

отметка времени == CAST(311957172.210091, "NSDate")

Первый вопрос: почему эти два числа не совпадают?

Второй и более важный вопрос: в ManagedContext у меня есть четыре записи с датами. Если я использую "‹=" вместо "==", я получаю результаты с датой меньше той, которую я передал, включая ту, которую я хочу получить. Почему я не могу получить одну дату с помощью оператора "=="? Может ли это быть связано с точностью моих дат?

Спасибо!


person denbec    schedule 21.11.2010    source источник


Ответы (3)


Это та же проблема, что и проверки на равенство с плавающей запятой, которые по своей сути небезопасны. Когда значения с плавающей запятой передаются, преобразуются, используются в арифметике и т. д., они постепенно теряют точность. Возможно, вам придется использовать более сложный предикат, который вместо этого проверяет даты в пределах определенного допуска; например,

NSArray *timestamps = [NSArray arrayWithObjects:
    [self.timestamp dateByAddingTimeInterval:-1],
    [self.timestamp dateByAddingTimeInterval:1],
    nil
];

NSPredicate *pre = [NSPredicate predicateWithFormat:@"timestamp BETWEEN %@", timestamps];

который даст вам любые объекты, соответствующие вашей дате, плюс или минус одна секунда.

person Justin Spahr-Summers    schedule 22.11.2010
comment
это почти сработало, спасибо! передача массива вызвала ошибку, но я передал два nsdates вручную в предикат, и теперь он работает. :) - person denbec; 22.11.2010
comment
Ой, извините за это! Рад, что это помогло, хотя. - person Justin Spahr-Summers; 22.11.2010
comment
Обратите внимание, что этот пример не будет работать с основными данными. Вам нужно использовать что-то вроде этого: zdam.posterous.com/core-data- выборка по дате - person SpaceTrucker; 14.11.2011

Первый вопрос: почему эти два числа не совпадают?

Внутренне NSDate, по-видимому, хранит отметку времени относительно 1 января 2001 г., а не 1 января 1970 г. Число 311957172.210091, вероятно, представляет собой количество секунд, прошедших с 01.01.2001.

Почему я не могу получить одну дату с помощью оператора "=="? Может ли это быть связано с точностью моих дат?

Я не знаю. Вы просматривали файл SQLite напрямую, чтобы увидеть, какие временные метки там хранятся?

person Ole Begemann    schedule 21.11.2010
comment
я получаю метку времени из своего магазина, передаю ее другому контроллеру представления и пытаюсь удалить ее там. поэтому я пытаюсь получить тот же объект; я передал временную метку заранее. это странно. есть ли другой способ удалить управляемый объект без предварительного получения этого объекта? - person denbec; 21.11.2010
comment
Почему вы передаете метку времени, а не сам объект? Нет необходимости получать его снова. - person Ole Begemann; 21.11.2010

Что касается вашего первого вопроса, держу пари, что числа совпадут, если вы используете [self.timestamp timeIntervalSinceReferenceDate], а не с 1970 года.

Что касается вашего второго вопроса, я предполагаю, что дата в хранилище управляемых объектов не совсем совпадает с self.timestamp. Например, может ли быть так, что сохраненная дата содержит только день, а не время? Возможно, вам придется сделать некоторое округление, чтобы они совпадали.

person Daniel Dickison    schedule 21.11.2010
comment
На самом деле, я использую временную метку или дату непосредственно из управляемого объекта, передаю ее другому контроллеру представления, делаю что-то еще и хочу снова ее удалить. поэтому мне нужен объект, чтобы удалить его из контекста, и я не знаю другого способа удалить объект, прежде чем снова его извлекать. так что это должна быть та же дата, которую я использую. - person denbec; 21.11.2010