Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data - Predicates with NSDates

Hallo,

I am working on a Core Data app and have to do some filtering based on dates. I've run some testing and it appears that when comparing NSDates, Core Data is comparing the time component of the dates as well.

My code:

- (BOOL)hasSpeakersWithinDateRangeFrom:(NSDate *)startOfRange through:(NSDate *)endOfRange {
    NSPredicate* dateRangePredicate = [NSPredicate predicateWithFormat:@"startOn <= %@ && endOn >= %@", startOfRange, endOfRange];
    NSSet* speakersWithinDateRange = [self.speakers filteredSetUsingPredicate:dateRangePredicate];

    if ([speakersWithinDateRange count] > 0)
        return YES;
    else
        return NO;
}

and I have a "convenience" method that is a one-line'er:

- (BOOL)hasSpeakersNow {
    return [self hasSpeakersWithinDateRangeFrom:[NSDate date] through:[NSDate date]];
}

When I run some basic testing, it doesn't work as planned, and from what I can tell Core Data is comparing the time components of the NSDate objects along with the dates.

So, how can I rewrite the above to ignore time and only be sensitive to the day passed?

Thank you

like image 347
Dale Tolar Avatar asked Apr 09 '26 17:04

Dale Tolar


2 Answers

You might want to get familiar with NSDateComponents and NSCalendar. What you will probably need to do is extract the components from your date and construct new NSDates using only the day, month, and year components without time components.

For the "current" day, you'll want to create a 1 day range by using today's date at midnight, and the date by adding 1 day to that. NSCalendar has methods to do some of this for you.

These docs might help:

  • NSCalendar Class Reference
  • NSDateComponents Class Reference
  • Date and Time Programming Guide
like image 74
Jason Foreman Avatar answered Apr 12 '26 06:04

Jason Foreman


This is essentially the same as vikingosegundo, but both functions use the same method, and I personally prefer it for my use.

- (NSDate *)dateByMovingToBeginningOfDay
{
  unsigned int flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
  NSDateComponents* parts = [[NSCalendar currentCalendar] components:flags fromDate:self];
  [parts setHour:0];
  [parts setMinute:0];
  [parts setSecond:0];
  return [[NSCalendar currentCalendar] dateFromComponents:parts];
}

- (NSDate *)dateByMovingToEndOfDay
{
  unsigned int flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
  NSDateComponents* parts = [[NSCalendar currentCalendar] components:flags fromDate:self];
  [parts setHour:23];
  [parts setMinute:59];
  [parts setSecond:59];
  return [[NSCalendar currentCalendar] dateFromComponents:parts];
}
like image 30
Daniel Amitay Avatar answered Apr 12 '26 06:04

Daniel Amitay



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!