我试图获取与用户selectedDate匹配的实体中的所有对象(它是NSDate)。 核心数据代码很好,但我的谓词不断返回0结果,数据库中的日期与用户选择的相同。
如何将selectedDate与使用谓词的实体的日期进行比较?
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eDate = %@)", selectedDate];
答案 0 :(得分:23)
你的谓词看起来很好。
返回结果为零的原因但可能是日期不完全相同。
例如:
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]]
答案 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