【问题标题】:How fetch objects with NSDate of today using NSPredicate?如何使用 NSPredicate 获取今天的 NSDate 对象?
【发布时间】:2016-02-28 22:12:54
【问题描述】:

我的核心数据模型和涉及日期的获取请求遇到问题。

我在具有 NSDate 属性的实体中有一些对象; 我需要提取今天日期的对象,但我总是从这段代码中得到 nil:

public func getObjectsOfToday() -> Array<myObject>?
{
    let entityDescription = NSEntityDescription.entityForName("Objects", inManagedObjectContext: DataAccess.sharedInstance.managedObjectContext)

    let request = NSFetchRequest()
    request.entity = entityDescription
    request.returnsObjectsAsFaults = false

    let today = NSDate()
    request.predicate = NSPredicate(format: "(dateStart => %@) AND (dateStart <= %@)", today, today)

    var objects: [AnyObject]?
    do
    {
        objects = try DataAccess.sharedInstance.managedObjectContext.executeFetchRequest(request)
    }
    catch let error as NSError
    {
        print(error)
        objects = nil
    }

    return objects as? Array<Objects>
}

我认为是 NSPredicate 的问题,因为它还考虑了小时、分钟和秒。如果我今天打印是这样的:

今日打印说明:2016-02-28 22:02:01 +0000

但是我想获取具有相同日期的对象,忽略小时、分钟和秒。我需要做什么?

我还尝试使用组件创建另一个 NSDate:

let components = cal.components([.Day , .Month, .Year ], fromDate: today)
let newDate = cal.dateFromComponents(components)

但结果是一样的。我做错了什么?

【问题讨论】:

    标签: ios swift core-data nsdate nspredicate


    【解决方案1】:

    我所做的是将它与一天的开始和结束进行比较,并使用几个辅助函数来计算它们:

    class DateHelper{
        internal class func startOfDay(day: NSDate) -> NSDate {
            let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
            let unitFlags: NSCalendarUnit = [.Minute, .Hour, .Day, .Month, .Year]
            let todayComponents = gregorian!.components(unitFlags, fromDate: day)
            todayComponents.hour = 0
            todayComponents.minute = 0
            return (gregorian?.dateFromComponents(todayComponents))!
        }
    
        internal class func endOfDay(day: NSDate) -> NSDate {
            let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
            let unitFlags: NSCalendarUnit = [.Minute, .Hour, .Day, .Month, .Year]
            let todayComponents = gregorian!.components(unitFlags, fromDate: day)
            todayComponents.hour = 23
            todayComponents.minute = 59
            return (gregorian?.dateFromComponents(todayComponents))!
        }
    }
    

    所以在你的代码中,你会调用:

    request.predicate = NSPredicate(format: "(dateStart => %@) AND (dateStart <= %@)", DateHelper.startOfDay(today), DateHelper.endOfDay(today))
    

    【讨论】:

    • 由于此代码不处理秒、纳秒和时代,因此在边缘情况下它可能会失败。此类方法更自然的地方是 NSDate 上的扩展而不是辅助类。
    • 这两点都很好——如果你有改进的地方,请随意!
    【解决方案2】:

    创建一个开始日期,获取一天的长度(间隔),将间隔添加到开始日期以获得第二天的开始。

    var startOfToday: NSDate?
    var interval: NSTimeInterval = 0
    
    NSCalendar.currentCalendar().rangeOfUnit(.Day, startDate: &startOfToday, interval: &interval, forDate: NSDate())
    let startOfTomorrow = startOfToday!.dateByAddingTimeInterval(interval)
    

    创建谓词

    let predicate = NSPredicate(format: "dateStart >= %@ AND dateStart < %@", startOfToday, startOfTomorrow)
    

    我使用以下测试代码没有核心数据的麻烦

    import Foundation
    
    let dates:[NSDate] = {
        var dates:[NSDate] = []
    
        dates.append({
            let c = NSDateComponents()
            c.year = 2016
            c.month = 2
            c.day = 1
            return NSCalendar.currentCalendar().dateFromComponents(c)!
        }())
    
        dates.append({
            let c = NSDateComponents()
            c.year = 2016
            c.month = 2
            c.day = 3
            return NSCalendar.currentCalendar().dateFromComponents(c)!
            }())
    
        dates.append({
            let c = NSDateComponents()
            c.year = 2016
            c.month = 3
            c.day = 1
            return NSCalendar.currentCalendar().dateFromComponents(c)!
            }())
        dates.append({
            let c = NSDateComponents()
            c.year = 2016
            c.month = 2
            c.day = 28
            c.hour = 12
            c.minute = 30
            return NSCalendar.currentCalendar().dateFromComponents(c)!
            }())
        dates.append({
            let c = NSDateComponents()
            c.year = 2016
            c.month = 2
            c.day = 28
            c.hour = 11
            c.minute = 15
            return NSCalendar.currentCalendar().dateFromComponents(c)!
            }())
        return dates
    }()
    
    
    var startOfToday: NSDate?
    var interval: NSTimeInterval = 0
    
    NSCalendar.currentCalendar().rangeOfUnit(.Day, startDate: &startOfToday, interval: &interval, forDate: NSDate())
    if let startOfToday = startOfToday  {
    
        let startOfTomorrow = startOfToday.dateByAddingTimeInterval(interval)
    
        let predicate = NSPredicate(format: "self >= %@ AND self < %@", startOfToday, startOfTomorrow)
    
        let filteredArray = dates.filter({predicate.evaluateWithObject($0)})
        print(filteredArray)
    }
    

    结果:

    [2016-02-28 11:30:00 +0000, 2016-02-28 10:15:00 +0000]
    

    【讨论】:

      猜你喜欢
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多