我需要计算最后几天,但无法弄清楚如何做到这一点。 例如,我得到了这样的核心数据:
|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 |
我尝试检查最后没有呈现(isPresent = 0)的日期直到今天并获得2016-02-14 - 所以我可以数天,这很容易。
但是,如果我将2016-02-14标记为isPresented = 1(如下表中所示),我将最后没有提交2016-02-11 - 但它不正确2016-02-13没有数据,因此,此日期的提示应为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 |
我为缺少日期(sql server displaying missing dates)搜索了不同的条纹或sql reuest算法,但无法弄清楚如何在核心数据中使用它。
我想到了另一个数据,每次用户打开应用程序时都会保持条纹和更新,但是如果用户没有打开应用程序会遇到同样的问题。
输出: 我需要在连胜或日期中找到天数,这是为了
对于第一个表:streak = 2或者breakDate = 2016-02-14 - 我试试这个,但我的解决方案错了,因为第二个表
对于第二张表:streak = 3或breakDate = 2016-02-13 - 无法弄清楚如何获取缺失日期
重要更新: 会有云同步数据,所以我在应用内部看不到任何解决方案,确实需要在coredata中找到缺失日期或isPresented = 0
p.s。我正在使用swift,如果你可以通过swift帮助我,那会很棒,但我也理解Obj-C。抱歉我的英语不好
答案 0 :(得分:1)
根据你的问题,我猜你有一个带有NSDate对象的item实体。以下是您可以使用的一些代码。
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
}
我将来电置于viewDidLoad
,但如果您愿意,可以将其添加到按钮中。
答案 1 :(得分:1)
所有SQL解决方案
请注意,这假定&#34;今天&#34;算作计算连胜的一天。 SQL以天数和条纹开始之前的日期返回条纹。
with max_zero_dt (zero_dt) as
(
select max(dt)
from (
select max(isPresent) as isPresent, dt from check_tab group by dt
union select 0, min(dt) from check_tab
)
where isPresent = 0
),
days_to_check (isPresent, dt) as
(
select isPresent, dt
from check_tab ct
join max_zero_dt on ( ct.dt >= zero_dt )
),
missing_days (isPresent, dt) as
(
select 0, date(dt, '-1 day') from days_to_check
UNION
select 0, date('now')
),
all_days_dups (isPresent, dt) as
(
select isPresent, dt from days_to_check
union
select isPresent, dt from missing_days
),
all_days (isPresent, dt) as
(
select max(isPresent) as isPresent, dt
from all_days_dups
group by dt
)
select cast(min(julianday('now') - julianday(dt)) as int) as day_streak
, max(dt) as dt
from all_days
where isPresent = 0
这是第一个场景的平方英尺:http://sqlfiddle.com/#!7/0f781/2
以下是第二种情况的平方英尺:http://sqlfiddle.com/#!7/155bb/2
关于FIDDLES的注意事项:他们将日期改为相对于&#34;今天&#34;这样它就能准确地测试条纹。
以下是它的工作原理:
假设: