我试图获取与用户 selectedDate 匹配的实体中的所有对象(它是 NSDate)。核心数据代码很好,但我的谓词一直返回 0 结果,数据库中的日期与用户选择的日期相同。
如何将 selectedDate 与使用谓词的实体的日期进行比较?
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eDate = %@)", selectedDate];
我试图获取与用户 selectedDate 匹配的实体中的所有对象(它是 NSDate)。核心数据代码很好,但我的谓词一直返回 0 结果,数据库中的日期与用户选择的日期相同。
如何将 selectedDate 与使用谓词的实体的日期进行比较?
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eDate = %@)", selectedDate];
你的谓词看起来很好。
您发现返回零结果的原因可能是日期不完全相同。
例如:
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]]
虽然在人类交流中,日期通常等于天,但与 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];
我可以对已接受的答案进行一些修改,并使用 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];
希望它可以帮助某人
我最近花了一些时间试图解决同样的问题并解决了以下问题,现在更新为 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]]
我在实际日期上下 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