如何计算核心数据中的连续天数?

Sek*_*eko 15 sql core-data objective-c ios swift

我需要计算最后几天,但无法弄清楚如何做到这一点.例如,我得到了这样的核心数据:

|id| isPresent(Bool)| date(NSDate)|
|==|================|=============|
| 1|               0| 2016-02-11  |
| 2|               1| 2016-02-11  |
| 3|               1| 2016-02-12  |
| 4|               0| 2016-02-14  |
| 5|               1| 2016-02-15  |
| 6|               1| 2016-02-16  |
| 7|               1| 2016-02-16  |
Run Code Online (Sandbox Code Playgroud)

我尝试检查最后没有呈现(isPresent = 0)日期直到今天并获得2016-02-14 - 所以我可以数天,这很容易.

但是,如果我将2016-02-14标记为isPresented = 1(如下表中所示)我将最后没有呈现2016-02-11 - 但它不正确2016-02-13没有数据,所以isPresented for此日期应为0,条纹应从此日期开始计算

|id| isPresent(Bool)| date(NSDate)|
|==|================|=============|
| 1|               0| 2016-02-11  |
| 2|               1| 2016-02-11  |
| 3|               1| 2016-02-12  |
| 4|               1| 2016-02-14  |
| 5|               1| 2016-02-15  |
| 6|               1| 2016-02-16  |
| 7|               1| 2016-02-16  |
Run Code Online (Sandbox Code Playgroud)

我搜索了不同的algoritm for streaks或sql reuests for missing dates(sql server显示缺少日期),但无法弄清楚如何在核心数据中使用它.

我想到了另一个数据,每次用户打开应用程序时都会保持条纹和更新,但如果用户没有打开应用程序则会遇到同样的问题.

输出: 我需要找到连续几天或连续几天的数量,所以

对于第一个表:streak = 2或breakDate = 2016-02-14 - 我试试这个,但我的解决方案错了,因为第二个表

对于第二个表:streak = 3或breakDate = 2016-02-13 - 无法弄清楚如何获取缺少日期

重要更新: 会有云同步数据,所以我在应用内部看不到任何解决方案,确实需要在coredata中找到缺失日期或isPresented = 0

ps我正在使用swift,如果你可以通过swift帮助我,那会很棒,但我也理解Obj-C.抱歉我的英语不好

D. *_*reg 4

从你的问题来看,我猜你有一个带有 NSDate 对象的项目实体。您可以使用以下代码来完成此操作。

let userDefaults = NSUserDefaults.standardUserDefaults()
var moc: NSManagedObjectContext!

var lastStreakEndDate: NSDate!
var streakTotal: Int!



override func viewDidLoad() {
    super.viewDidLoad()


    // checks for object if nil creates one (used for first run)
    if userDefaults.objectForKey("lastStreakEndDate") == nil {
        userDefaults.setObject(NSDate(), forKey: "lastStreakEndDate")
    }

    lastStreakEndDate = userDefaults.objectForKey("lastStreakEndDate") as! NSDate

    streakTotal = calculateStreak(lastStreakEndDate)
}


// fetches dates since last streak
func fetchLatestDates(moc: NSManagedObjectContext, lastDate: NSDate) -> [NSDate] {
    var dates = [NSDate]()

    let fetchRequest = NSFetchRequest(entityName: "YourEntity")
    let datePredicate = NSPredicate(format: "date < %@", lastDate)

    fetchRequest.predicate = datePredicate

    do {
        let result = try moc.executeFetchRequest(fetchRequest)
        let allDates = result as! [NSDate]
        if allDates.count > 0 {
            for date in allDates {
                dates.append(date)
            }
        }
    } catch {
        fatalError()
    }
    return dates
}


// set date time to the end of the day so the user has 24hrs to add to the streak
func changeDateTime(userDate: NSDate) -> NSDate {
    let dateComponents = NSDateComponents()
    let currentCalendar = NSCalendar.currentCalendar()
    let year = Int(currentCalendar.component(NSCalendarUnit.Year, fromDate: userDate))
    let month = Int(currentCalendar.component(NSCalendarUnit.Month, fromDate: userDate))
    let day = Int(currentCalendar.component(NSCalendarUnit.Day, fromDate: userDate))

    dateComponents.year = year
    dateComponents.month = month
    dateComponents.day = day
    dateComponents.hour = 23
    dateComponents.minute = 59
    dateComponents.second = 59

    guard let returnDate = currentCalendar.dateFromComponents(dateComponents) else {
        return userDate
    }
    return returnDate
}


// adds a day to the date
func addDay(today: NSDate) -> NSDate {
    let tomorrow = NSCalendar.currentCalendar().dateByAddingUnit(.Day, value: 1, toDate: today, options: NSCalendarOptions(rawValue: 0))

    return tomorrow!
}

// this method returns the total of the streak and sets the ending date of the last streak
func calculateStreak(lastDate: NSDate) -> Int {
    let dateList = fetchLatestDates(moc, lastDate: lastDate)
    let compareDate = changeDateTime(lastDate)
    var streakDateList = [NSDate]()
    var tomorrow = addDay(compareDate)

    for date in dateList {
        changeDateTime(date)
        if date == tomorrow {
           streakDateList.append(date)
        }
        tomorrow = addDay(tomorrow)
    }

    userDefaults.setObject(streakDateList.last, forKey: "lastStreakEndDate")
    return streakDateList.count
}
Run Code Online (Sandbox Code Playgroud)

我将呼叫放在 中viewDidLoad,但如果您愿意,您可以将其添加到按钮中。