Я застрял в проблеме с моей моделью Core Data и запросом на выборку, который включает даты.

У меня есть несколько объектов в сущности с атрибутом NSDate; Мне нужно извлечь объекты с сегодняшней датой , но я всегда получаю ноль из этого кода:

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)

Но результат тот же. Что я делаю не так?

1
Massimo Polimeni 29 Фев 2016 в 01:12

2 ответа

Лучший ответ

Что я делаю, так это сравниваю его с началом и концом дня и имею пару вспомогательных функций для их вычисления:

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))
5
sschale 29 Фев 2016 в 21:32

Создать дату начала, получить длину дня (интервал), добавить интервал к дате начала, чтобы получить начало следующего дня.

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]
1
vikingosegundo 29 Фев 2016 в 00:49