我想搜索所有现有对象,以查看CoreData中是否有任何匹配的日期对象:
日期目前通过 start_date 属性保存在我的CoreData中,格式如下:2013-08-29 14:27:47 +0000。
然后我让用户从UIDatePicker中选择日期并将.date()分配给变量日期。
e.g。我的选择日期 = 2013-08-29 17:34:23 +0000。
以下是我使用谓词搜索CoreData的方法。
let predicate = NSPredicate(format: "start_date contains[search] %@", date)
let request:NSFetchRequest = NSFetchRequest(entityName: "Project")
let sortDescriptor:NSSortDescriptor = NSSortDescriptor(key: "number", ascending: true)
let sortDescriptorsAry:NSArray = [sortDescriptor]
request.sortDescriptors = sortDescriptorsAry
request.predicate = predicate
return request
然而我没有结果。我认为这是因为两个属性因时间而不匹配:
start_date = 2013-08-29 14:27:47 +0000
date = 2013-08-29 17:34:23 +0000
我怎么能告诉CoreData忽略" 177:34:23 + 0000"有点,还是有更好的方法?
编辑:
我可以选择更改最初存储日期格式的方式:
我试过这个:
var now:NSDate = self.startDatePicker.date
var calendar:NSCalendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)
var components:NSDateComponents = calendar.components(NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay, fromDate: now)
components.hour = 00
components.minute = 00
components.second = 00
var newDate:NSDate = calendar.dateFromComponents(components)!
然而在某些日子里,我的时间定在前一天。 例如:
选择8月30日,改造后我得到2014-08-29 23:00:00 +0000
答案 0 :(得分:2)
在Core Data中保存start_date
属性之前,您需要确保他们的时间设置为12:00 AM:
//Get "Aug 29, 2014, 12:00 AM" from "Aug 29, 2014, 10:07 PM"
let newDate = NSDate() //or any other date
let calendar = NSCalendar.currentCalendar()
calendar.timeZone = NSTimeZone.systemTimeZone()
var startDate: NSDate?
var duration: NSTimeInterval = 0
calendar.rangeOfUnit(.DayCalendarUnit, startDate: &startDate, interval: &duration, forDate: newDate)
//Create, set and save a new managedObject
//Records, here, is the name of your NSManagedObject subclass
let record = NSEntityDescription.insertNewObjectForEntityForName("Records", inManagedObjectContext: managedObjectContext) as Records
record.start_date = startDate
/* set other attributes here */
var error: NSError?
if !managedObjectContext.save(&error) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
println("Unresolved error \(error), \(error!.userInfo)")
abort()
}
然后,您将能够使用您想要的谓词在Core Data中获取日期:
//Set your datePicker date to 12:00 AM
let pickerDate = dateFromMyDatePicker //as NSDate
let calendar = NSCalendar.currentCalendar()
calendar.timeZone = NSTimeZone.systemTimeZone()
var predicateDate: NSDate?
var duration: NSTimeInterval = 0
calendar.rangeOfUnit(.DayCalendarUnit, startDate: &predicateDate, interval: &duration, forDate: pickerDate)
//Create your fetchRequest
/* ... */
//Set your predicate
let predicate = NSPredicate(format: "start_date == %@", predicateDate)
修改强>
作为rangeOfUnit:startDate:interval:forDate:
的替代方案,您可以使用您提供的代码。但在这两种情况下,请不要忘记添加以下行:
calendar.timeZone = NSTimeZone.systemTimeZone()
答案 1 :(得分:1)
<edit>
在我看来,第二种做事方式似乎是一种很好的方式。存储年,月和日的整数值,并使用该值创建谓词。您对NSDateComponents和日历的使用非常好,因此这应该是最简单的方法。非常重要:不要使用00的时间,因为午夜是一个棘手的时间(在世界的某些地方有夏令时,有一个问题是午夜是否是第二天的前一部分)。只需输入12作为时间,尽可能远离午夜。 此外,我建议你从2011年的“执行日历计算,会议117”观看WWDC。它讨论了其他非常有趣的事情,关于为什么午夜很棘手(如果没有,那么在2013年会议中解释:)。/ p>
</edit>
NSDate具有亚秒级的准确性。它的描述方法(在NSLog NSDate时调用)仅显示第二精度。 因此,要在NSPredicate中使用NSDate,请始终指定“大于/小于或等于”运算符。
例如:
NSDate * lastWeek = // ... created using NSCalendar and NSDateComponents.
NSDate * now = [NSDate date];
NSPredicate * entitiesFromAfterLastWeekAndBeforeNow = [NSPredicate predicateWithFormat: @"start_date >= %@ AND start_date <= %@", lastWeek, now];
我建议不要将数据存储在原生NSDate的其他内容中,因为您可能会存储由于转换而导致错误的日期。此外,将日期存储为字符串将使查询慢得多(因为必须解析字符串,而NSDate只是一个数字)。但这是另一个讨论,你可能想发货,所以你必须做你认为最好的事情。
编辑:对不起,现在才注意到你正在写Swift。但我认为我的例子很清楚它可以转换为Swift,对吧?
答案 2 :(得分:1)
如果您仍然需要更改存储数据的方式,我会将其存储在您的项目实体中作为三个属性:年份的整数,月份的整数和白天的整数。编码会更容易(你可以创建一个谓词:
NSInteger year = ....
NSInteger month = ....
NSInteger day = ....
[NSPredicate predicateWithFormat: @"day == %@ AND month == %@ and year == %@", @(day), @(month), @(year)];
)与使用字符串相比,这可能更快。如果你想使用字符串(注意无关的空格或其他交集!),你可以在代码中构造一个格式为&#39; yyyy-mm-dd&#39;的字符串。 (使用NSString stringWithFormat :)然后使用NSPredicate,如:
NSInteger year = ....
NSInteger month = ....
NSInteger day = ....
NSString * dateString = [NSStringWithFormat: @"%4i-%2i-%2i", year, month, day];
[NSPredicate predicateWithFormat: @"dateString contains %@", dateString];
但是,只有在您构建了存储的字符串而不是NSDate.description()时,这才有效。如果您存储实际的NSDate,请参阅我的第一个原始答案:)。
但实际上,如果您仍有选项,请不要将其存储为字符串。如果不是现在,那么它确实会成为问题,然后(我可以从经验中得知)。