核心数据谓词日期比较

时间:2013-04-05 10:30:19

标签: objective-c cocoa nsdate predicate

我试图获取与用户selectedDate匹配的实体中的所有对象(它是NSDate)。 核心数据代码很好,但我的谓词不断返回0结果,数据库中的日期与用户选择的相同。

如何将selectedDate与使用谓词的实体的日期进行比较?

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eDate = %@)", selectedDate];

5 个答案:

答案 0 :(得分:23)

你的谓词看起来很好。

返回结果为零的原因但可能是日期不完全相同。

例如:

05/04/2012 13:37:0005/04/2012 13:37:01不匹配,因为这两个值并不完全相同。

您想查看日期(日,月,年)以及时间吗?

如果您只想查看日期,则应创建开始日期和结束日期,并使用用户选择的日期作为参考框架进行比较。

类似的东西应该为00:00:00创建一个日期和时间。

//gather current calendar
NSCalendar *calendar = [NSCalendar currentCalendar];

//gather date components from date
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDate date]];

//set date components
[dateComponents setHour:0];
[dateComponents setMinute:0];
[dateComponents setSecond:0];

//return date relative from date
return [calendar dateFromComponents:dateComponents];

通过将小时,分钟和秒设置为23:59:59来创建另一个日期,并检查用户选择的日期是否介于这些范围之间。

[NSPredicate predicateWithFormat:@"date BETWEEN %@", [NSArray arrayWithObjects:startOfDay, endOfDay, nil]]

答案 1 :(得分:12)

虽然在人类交流日期通常与日期相同,但与NSDate对象不同:NSDate代表单个时刻。几秒钟内不同的日期不相等。实际上它们根本不代表日,月,年,因为这与日历系统到日历系统不同

你必须自己定义同一分钟,小时,日......的日期是否相等。所以基本上你必须教会程序以允许一些模糊。

这里是分钟分辨率

NSDate *startDate = ....;
NSTimeInterval length;

[[NSCalendar currentCalendar] rangeOfUnit:NSMinuteCalendarUnit 
                                startDate:&startDate
                                 interval:&length 
                                  forDate:startDate];

NSDate *endDate = [startDate dateByAddingTimeInterval:length];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eDate >= %@) AND (eDate < %@)", startDate, endDate];

对于同一天的日期(了解时区和夏令时),您只需更改此内容:

[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit 
                                startDate:&startDate
                                 interval:&length 
                                  forDate:startDate];

答案 2 :(得分:2)

我可以对已接受的答案进行一些修改,并使用iOS 8 API创建具有时间偏移的创建日期。代码:

Makefile

希望它有助于某人

答案 3 :(得分:0)

我最近花了一些时间尝试解决同样的问题并解决了以下问题,现在已针对iOS 8及更高版本进行了更新...

NSDate *dateDay = nil;
NSDate *dateDayStart = nil;
NSDate *dateDayNext = nil;

dateDay = <<USER_INPUT>>;  //for example - selectedDate

dateDayStart = [[NSCalendar currentCalendar] startOfDayForDate:dateDay];

//  dateDayNext EITHER
dateDayNext = [dateDayStart dateByAddingTimeInterval:(24 * 60 * 60)];

//  dateDayNext OR
NSDateComponents *dateComponentDay = nil;
dateComponentDay = [[NSDateComponents alloc] init];
[dateComponentDay setDay:1];
dateDayNext = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponentDay
                                                            toDate:dateDayStart
                                                           options:NSCalendarMatchNextTime];

...以及核心数据NSPredicate的{​​{1}}(如上文其他答案所示)......

NSFetchRequest

答案 4 :(得分:0)

我在实际日期的上下1秒之间进行查询。就我而言,我可以在查询餐厅订单时加减1秒,因此我知道打一个新订单要花一些时间,为了安全起见,我还有1个orderNo字段。

    let fetchRequest: NSFetchRequest = Order.fetchRequest()
    let date_formatter = DateFormatter()
    date_formatter.dateFormat = "yyyy-MM-dd-HH-mm-ss"
    date_formatter.timeZone = TimeZone(abbreviation: "UTC")

    let createdDate = date_formatter.date(from: clientCreatedStr)

    let calendar = NSCalendar.current

    //as matching exact same datetime doesnt return anything
    let onesecondafter = calendar.date(byAdding: .second, value: 1, to: createdDate!)
    let onesecondbefore = calendar.date(byAdding: .second, value: -1, to: createdDate!)

    let predicate = NSPredicate(format: "offlineUniqueId == %@ AND (clientCreatedDate >= %@ AND clientCreatedDate <= %@)", offlineUniqueId, onesecondbefore! as NSDate, onesecondafter! as NSDate)

    fetchRequest.predicate = predicate