2016-02-16 14 views
15

私は日の最後の連勝をカウントする必要がありますが、これを行う方法を見つけ出すことはできません。例えば は、私はこのようなコアデータだ:私は今日まで続く提示されていない(isPresent = 0)日付を確認し、2016年2月14日取得しようコアデータの日数を計算する方法は?

|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 | 

- ので、私は日を数えることができるが、それは簡単です。

しかし、2016-02-14をisPresented = 1(表の下のようなもの)としてマークすると、最後には表示されません2016-02-11 - ただし、正しくありません2016-02-13この日のためにisPresentedので0でなければならず、ストリークは、コアデータでそれを使用する方法を見つけ出すカント私は別の行方不明日付の筋やSQL reuestsのためのそのアルゴリズム(sql server displaying missing dates)が、検索

|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 | 

この日から数える必要があります。

私はストリークやアップデート、ユーザーがアプリを開いたが、ユーザが開いてアプリをしなかった場合はどのような同じ問題を抱えてすべての時間を維持します別のデータについて考えます。

出力: 私は最初のテーブルについて

のためので、それが壊れたときにちょうどスジや日付に日数をカウントしたする必要があります= 2スジやbreakDate = 2016年2月14日 - 私はこれを試してみてくださいが、2番目のテーブルのために第二のテーブル

ので、間違って私の解決策:= 3またはbreakDate = 2016年2月13日ストリークは - 行方不明取得する方法を見つけ出すことはできません

日付が重要な更新: がありますクロであるudの同期データ、私はアプリ内の任意のソリューションが表示されない、本当に欠けている日付を見つける必要があるか、またはcoredataでisPresented = 0

p.s.あなたはそれは素晴らしいことだSWIFT経由で私を助けることができる場合、私は迅速使用していますが、私はまた、OBJの-Cを理解しています。そして、あなたの質問から私の悪い英語

+0

一部のセレクタでデータを取得できます。これは助けになるかもしれませんが、あなたの質問ではありません。 – Lumialxk

+0

あなたの期待する出力を表示してください – sagi

+0

@sagi add Output – Seko

答えて

1

のため申し訳ありませんが、私はあなたが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 
} 

私はviewDidLoadに電話を入れたが、あなたが好きなら、あなたはボタンに追加することができます。

+0

ありがとう、D.グレッグ、できるだけ早くそれをチェックします。完全に理解していないが、主なアイデアを理解する。 – Seko

+0

calculateStreakのforループは何ですか? – Seko

+0

特に、複数の日付(例: – Seko

1

ALL SQLソリューション

これは「今日は」計算のためにストリークで一日としてカウントされていることを前提としていますのでご注意ください。 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 

は、最初のシナリオのためのsqlfiddleである:ここでhttp://sqlfiddle.com/#!7/0f781/2

は、2番目のシナリオのためのsqlfiddleです:フィドルABOUT http://sqlfiddle.com/#!7/155bb/2

注:彼らは今日」への相対値で日付を変更します"それは正確にストリークをテストするように。ここで

は、それがどのように動作するかです:

  • 概要:我々はゼロで行方不明の日「に記入」、その後、最大0日付があるときに表示するための簡単なチェックをするつもりされています。しかし、今日の行がなく、ゼロの行がない場合は、考慮する必要があります。
  • max_zero_dt:最新の明示的な0の日付、または最も古い日付から1日を引いた1つの行が含まれます。これは、後の照会の行数を減らすためです。
  • days_to_check:これは、最新の0がいつであるかに基づいてチェックされる行数を減らしたものです。
  • missing_days:不足している曜日を記入する必要があるため、すべての曜日から1日を引いたものを取得します。また、行がない場合に備えて、今日追加します。
  • all_days_dups:days_to_checkとmissing_daysを単に組み合わせます。
  • all_days:ここで、毎日の 'max' isPresentを取得します。ここで、isPresentに0の空白がないことを知り、真の検索日を探します。
  • 最終クエリ:ストリークと開始日を指定する単純な計算です。

の仮定:

  • テーブル名は次のとおりです。check_tab
  • 現在の日付がそうでなければ1と表内にある必要があり、ストリークはこれがない場合は、クエリを変更することができます0です。ケース。
  • isPresentに1日が0と1の両方を持つ場合は、1が優先され、ストリークは前回まで続くことができます。
  • コアデータがSQLiteを使用し、SQLiteで動作する上記のSQLもコアデータのデータベースで動作します。
関連する問題