开发者

Using NSPredicate to fetch exact NSDate from NSManagedObjectContect

I'm trying to fetch results of my entity "MeterReading", which has two properties, "timestamp" and "reading". "timestamp" is an NSDate. I'm now trying to fetch an object with an exact date.

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];

Now, self.timestamp is passed to another ViewController beforehand, the NSLog shows:

1290264372.210091

The NSPredicate logs

timestamp == CAST(311957172.210091, "NSDate")

First question: Why aren't the two numbers the same?

Second and more important question: In the ManagedContext, I have four entries with dates. If I use "<=" instead of "==", I 开发者_高级运维do get results with a date smaller than the one I passed, including the one I want to have. Why can't I get the one single date with the "==" operator? Can this be related to precision of my dates?

Thanks!


This is the same issue as floating-point equality checks being inherently unsafe. As floating-point values get passed around, converted, used in arithmetic, etc., they lose accuracy bit by bit. You may have to use a more complex predicate that instead checks for dates within a certain tolerance; for instance,

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

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

which would get you any objects matching your date plus or minus one second.


First question: Why aren't the two numbers the same?

Internally, NSDate seems to store a timestamp relative to January 1, 2001, and not January 1, 1970. The number 311957172.210091 probably is the number of seconds since 01/01/2001.

Why can't I get the one single date with the "==" operator? Can this be related to precision of my dates?

I don't know. Have you inspected the SQLite file directly to see which timestamps are stored there?


For your first question, I bet the numbers will match if you used [self.timestamp timeIntervalSinceReferenceDate] instead of since 1970.

For your second question, my hunch is that the date in the managed object storage is not exactly the same as self.timestamp. For instance, could it be that the stored date only contains a day and not time? You might need to do some rounding to get those to match.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜