NSPredicate - to search for events that occur between a specific date range

It's a little trickier than just

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"startDate >= %@ AND endDate <= %@", startDay,endDay];

I am creating a calendar application, and I need to pull events from my main data store that occur on a given day. However, it is possible that the event will start / end on another day, and then on the day when I try to display, for example.

My date range (start = 2011-12-02 00:00:00 to end = 2011-12-02 23:59:59)

Event (start = 2011-12-01 23:00:00 to the end = 2011-12-02 05:00:00)

How to write a predicate to determine if this event falls into this date range. Keep in mind that an event can start before and after a date range.

Thank!

+3
4

, ( ):

- (NSPredicate *) predicateToRetrieveEventsForDate:(NSDate *)aDate {

    // start by retrieving day, weekday, month and year components for the given day
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *todayComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:aDate];
    NSInteger theDay = [todayComponents day];
    NSInteger theMonth = [todayComponents month];
    NSInteger theYear = [todayComponents year];

    // now build a NSDate object for the input date using these components
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setDay:theDay]; 
    [components setMonth:theMonth]; 
    [components setYear:theYear];
    NSDate *thisDate = [gregorian dateFromComponents:components];
    [components release];

    // build a NSDate object for aDate next day
    NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
    [offsetComponents setDay:1];
    NSDate *nextDate = [gregorian dateByAddingComponents:offsetComponents toDate:thisDate options:0];
    [offsetComponents release];

    [gregorian release];


    // build the predicate 
    NSPredicate *predicate = [NSPredicate predicateWithFormat: @"startDate < %@ && endDate > %@", nextDate, thisDate];

        return predicate;

}

, @Tony, , . . , , 8 23:00 9 00:00. , > =, > , 8 9 , . iCal, Google Calendar, , 8 . , 23:59:59 ( , , true): ( ). , , , .

+13

:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"startDate <= %@ AND endDate >= %@", endDay, startDay];

, , , .. , .

+7

Although the proposed solution is correct, it is also quite verbose. I updated it in Swift 3.0:

import Foundation

extension NSPredicate {

    static func filter(key: String, onDayRangeForDate date: Date, calendar: Calendar = Calendar(identifier: .gregorian)) -> NSPredicate {

        let dateComponents = calendar.dateComponents([.day, .month, .year], from: date)

        let startOfDay = calendar.date(from: dateComponents)!

        let offsetComponents = NSDateComponents()
        offsetComponents.day = 1
        let endOfDay = calendar.date(byAdding: offsetComponents as DateComponents, to: startOfDay)!

        return NSPredicate(format: "\(key) >= %@ && \(key) < %@",
            startOfDay as NSDate, endOfDay as NSDate)
    }
}
+1
source
Massimo Camaro received an excellent response. I put it in Swift and modified it a bit to support a different column name.

Swift 2.0

func predicateToRetrieveEventsForDate(aDate:NSDate, predicateColumn:String) -> NSPredicate {

    // start by retrieving day, weekday, month and year components for the given day
    let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
    let todayComponents = gregorian?.components([.Day, .Month, .Year], fromDate: aDate)
    let theDay = todayComponents?.day
    let theMonth = todayComponents?.month
    let theYear = todayComponents?.year

    // now build a NSDate object for the input date using these components
    let components = NSDateComponents()
    components.day = theDay!
    components.month = theMonth!
    components.year = theYear!
    let thisDate = gregorian?.dateFromComponents(components)

    // build a NSDate object for aDate next day
    let offsetComponents = NSDateComponents()
    offsetComponents.day = 1
    let nextDate = gregorian?.dateByAddingComponents(offsetComponents, toDate: thisDate!, options: NSCalendarOptions(rawValue: 0))

    // build the predicate
    let predicate = NSPredicate(format: "\(predicateColumn) >= %@ && \(predicateColumn) < %@", thisDate!, nextDate!)

    return predicate
}
0
source

Source: https://habr.com/ru/post/1752885/


All Articles