16

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

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

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

5 回答 5

25

你的谓词看起来很好。

您发现返回零结果的原因可能是日期不完全相同。

例如:

05/04/2012 13:37:00将不匹配,05/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]]
于 2013-04-05T10:56:30.920 回答
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];
于 2013-04-05T11:00:54.553 回答
2

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

NSCalendar *calendar = [[FFSharedCalendar singleton] getGregorianCalendar];
NSDate *startOfDay = [calendar dateBySettingHour:0 minute:0 second:0 ofDate:[NSDate date] options:0];
NSDate *endOfDay = [calendar dateBySettingHour:23 minute:59 second:59 ofDate:[NSDate date] options:0];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"createdAt > %@ AND createdAt < %@", startOfDay, endOfDay];
NSArray* plans = [Plan MR_findAllWithPredicate:predicate];

希望它可以帮助某人

于 2016-04-25T06:03:11.757 回答
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核心数据NSFetchRequest(如上面其他答案中所示)...

[NSPredicate predicateWithFormat:@"(dateAttribute >= %@) AND (dateAttribute < %@)", dateDayStart, dateDayNext]]
于 2016-04-05T04:51:36.900 回答
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
于 2020-04-09T16:10:36.087 回答