Quellcode durchsuchen

Centralized date parsing

Jonas Björkert vor 2 Jahren
Ursprung
Commit
6dd36bb84b

+ 8 - 26
LoopFollow/Controllers/Nightscout/Treatments/BGCheck.swift

@@ -13,37 +13,19 @@ extension MainViewController {
     // NS BG Check Response Processor
     func processNSBGCheck(entries: [[String:AnyObject]]) {
         if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Process: BG Check") }
-        // because it's a small array, we're going to destroy and reload every time.
         bgCheckData.removeAll()
-        for i in 0..<entries.count {
-            let currentEntry = entries[entries.count - 1 - i] as [String : AnyObject]?
-            var date: String
-            if currentEntry?["timestamp"] != nil {
-                date = currentEntry?["timestamp"] as! String
-            } else if currentEntry?["created_at"] != nil {
-                date = currentEntry?["created_at"] as! String
-            } else {
-                return
-            }
-            // Fix for FreeAPS milliseconds in timestamp
-            var strippedZone = String(date.dropLast())
-            strippedZone = strippedZone.components(separatedBy: ".")[0]
-            
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
-            dateFormatter.locale = Locale(identifier: "en_US")
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            let dateString = dateFormatter.date(from: strippedZone)
-            let dateTimeStamp = dateString!.timeIntervalSince1970
+        
+        entries.reversed().forEach { currentEntry in
+            guard let dateStr = currentEntry["timestamp"] as? String ?? currentEntry["created_at"] as? String else { return }
             
-            guard let sgv = currentEntry?["glucose"] as? Int else {
-                if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "ERROR: Non-Int Glucose entry")}
-                continue
+            guard let parsedDate = NightscoutUtils.parseDate(dateStr),
+                  let sgv = currentEntry["glucose"] as? Int else {
+                if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "ERROR: Non-Int Glucose entry") }
+                return
             }
             
+            let dateTimeStamp = parsedDate.timeIntervalSince1970
             if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
-                // Make the dot
-                //let dot = ShareGlucoseData(value: Double(carbs), date: Double(dateTimeStamp), sgv: Int(sgv.sgv))
                 let dot = ShareGlucoseData(sgv: sgv, date: Double(dateTimeStamp), direction: "")
                 bgCheckData.append(dot)
             }

+ 10 - 17
LoopFollow/Controllers/Nightscout/Treatments/Bolus.swift

@@ -14,28 +14,21 @@ extension MainViewController {
         // because it's a small array, we're going to destroy and reload every time.
         bolusData.removeAll()
         var lastFoundIndex = 0
-        for i in 0..<entries.count {
-            let currentEntry = entries[entries.count - 1 - i] as [String : AnyObject]?
+        
+        entries.reversed().forEach { currentEntry in
             var bolusDate: String
-            if currentEntry?["timestamp"] != nil {
-                bolusDate = currentEntry?["timestamp"] as! String
-            } else if currentEntry?["created_at"] != nil {
-                bolusDate = currentEntry?["created_at"] as! String
+            if currentEntry["timestamp"] != nil {
+                bolusDate = currentEntry["timestamp"] as! String
+            } else if currentEntry["created_at"] != nil {
+                bolusDate = currentEntry["created_at"] as! String
             } else {
-                continue
+                return
             }
             
-            // fix to remove millisecond (after period in timestamp) for FreeAPS users
-            var strippedZone = String(bolusDate.dropLast())
-            strippedZone = strippedZone.components(separatedBy: ".")[0]
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
-            dateFormatter.locale = Locale(identifier: "en_US")
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            guard let dateString = dateFormatter.date(from: strippedZone) else { continue }
-            let dateTimeStamp = dateString.timeIntervalSince1970
+            guard let parsedDate = NightscoutUtils.parseDate(bolusDate),
+                  let bolus = currentEntry["insulin"] as? Double else { return }
             
-            guard let bolus = currentEntry?["insulin"] as? Double else { continue }
+            let dateTimeStamp = parsedDate.timeIntervalSince1970
             let sgv = findNearestBGbyTime(needle: dateTimeStamp, haystack: bgData, startingIndex: lastFoundIndex)
             lastFoundIndex = sgv.foundIndex
             

+ 14 - 33
LoopFollow/Controllers/Nightscout/Treatments/Carbs.swift

@@ -11,39 +11,27 @@ extension MainViewController {
     // NS Carb Bolus Response Processor
     func processNSCarbs(entries: [[String:AnyObject]]) {
         if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Process: Carbs") }
-        // because it's a small array, we're going to destroy and reload every time.
+        // Because it's a small array, we're going to destroy and reload every time.
         carbData.removeAll()
         var lastFoundIndex = 0
         var lastFoundBolus = 0
-        for i in 0..<entries.count {
-            let currentEntry = entries[entries.count - 1 - i] as [String : AnyObject]?
+        
+        entries.reversed().forEach { currentEntry in
             var carbDate: String
-            if currentEntry?["timestamp"] != nil {
-                carbDate = currentEntry?["timestamp"] as! String
-            } else if currentEntry?["created_at"] != nil {
-                carbDate = currentEntry?["created_at"] as! String
+            if currentEntry["timestamp"] != nil {
+                carbDate = currentEntry["timestamp"] as! String
+            } else if currentEntry["created_at"] != nil {
+                carbDate = currentEntry["created_at"] as! String
             } else {
-                continue
+                return
             }
             
+            let absorptionTime = currentEntry["absorptionTime"] as? Int ?? 0
             
-            let absorptionTime = currentEntry?["absorptionTime"] as? Int ?? 0
-            
-            // Fix for FreeAPS milliseconds in timestamp
-            var strippedZone = String(carbDate.dropLast())
-            strippedZone = strippedZone.components(separatedBy: ".")[0]
-            
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
-            dateFormatter.locale = Locale(identifier: "en_US")
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            guard let dateString = dateFormatter.date(from: strippedZone) else { continue }
-            var dateTimeStamp = dateString.timeIntervalSince1970
+            guard let parsedDate = NightscoutUtils.parseDate(carbDate),
+                  let carbs = currentEntry["carbs"] as? Double else { return }
             
-            guard let carbs = currentEntry?["carbs"] as? Double else {
-                if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "ERROR: Null Carb entry")}
-                continue
-            }
+            let dateTimeStamp = parsedDate.timeIntervalSince1970
             let sgv = findNearestBGbyTime(needle: dateTimeStamp, haystack: bgData, startingIndex: lastFoundIndex)
             lastFoundIndex = sgv.foundIndex
             
@@ -52,11 +40,7 @@ extension MainViewController {
                 let bolusTime = findNearestBolusbyTime(timeWithin: 300, needle: dateTimeStamp, haystack: bolusData, startingIndex: lastFoundBolus)
                 lastFoundBolus = bolusTime.foundIndex
                 
-                if bolusTime.offset {
-                    offset = 70
-                } else {
-                    offset = 20
-                }
+                offset = bolusTime.offset ? 70 : 20
             }
             
             if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
@@ -89,10 +73,7 @@ extension MainViewController {
                 continue
             }
             
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            guard let date = dateFormatter.date(from: carbDate) else {
+            guard let date = NightscoutUtils.parseDate(carbDate) else {
                 print("Unable to parse date from: \(carbDate)")
                 continue
             }

+ 22 - 25
LoopFollow/Controllers/Nightscout/Treatments/Notes.swift

@@ -16,38 +16,35 @@ extension MainViewController {
         // because it's a small array, we're going to destroy and reload every time.
         noteGraphData.removeAll()
         var lastFoundIndex = 0
-        for i in 0..<entries.count {
-            let currentEntry = entries[entries.count - 1 - i] as [String : AnyObject]?
+        
+        entries.reversed().forEach { currentEntry in
+            guard let currentEntry = currentEntry as? [String: AnyObject] else { return }
+            
             var date: String
-            if currentEntry?["timestamp"] != nil {
-                date = currentEntry?["timestamp"] as! String
-            } else if currentEntry?["created_at"] != nil {
-                date = currentEntry?["created_at"] as! String
+            if currentEntry["timestamp"] != nil {
+                date = currentEntry["timestamp"] as! String
+            } else if currentEntry["created_at"] != nil {
+                date = currentEntry["created_at"] as! String
             } else {
                 return
             }
-            // Fix for FreeAPS milliseconds in timestamp
-            var strippedZone = String(date.dropLast())
-            strippedZone = strippedZone.components(separatedBy: ".")[0]
-            
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
-            dateFormatter.locale = Locale(identifier: "en_US")
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            let dateString = dateFormatter.date(from: strippedZone)
-            let dateTimeStamp = dateString!.timeIntervalSince1970
-            
-            let sgv = findNearestBGbyTime(needle: dateTimeStamp, haystack: bgData, startingIndex: lastFoundIndex)
-            lastFoundIndex = sgv.foundIndex
             
-            guard let thisNote = currentEntry?["notes"] as? String else { continue }
-            
-            if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
-                // Make the dot
-                let dot = DataStructs.noteStruct(date: Double(dateTimeStamp), sgv: Int(sgv.sgv), note: thisNote)
-                noteGraphData.append(dot)
+            if let parsedDate = NightscoutUtils.parseDate(date) {
+                let dateTimeStamp = parsedDate.timeIntervalSince1970
+                let sgv = findNearestBGbyTime(needle: dateTimeStamp, haystack: bgData, startingIndex: lastFoundIndex)
+                lastFoundIndex = sgv.foundIndex
+                
+                guard let thisNote = currentEntry["notes"] as? String else { return }
+                
+                if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
+                    let dot = DataStructs.noteStruct(date: Double(dateTimeStamp), sgv: Int(sgv.sgv), note: thisNote)
+                    noteGraphData.append(dot)
+                }
+            } else {
+                print("Failed to parse date")
             }
         }
+        
         if UserDefaultsRepository.graphOtherTreatments.value {
             updateNotes()
         }

+ 19 - 65
LoopFollow/Controllers/Nightscout/Treatments/Overrides.swift

@@ -13,89 +13,43 @@ extension MainViewController {
     // NS Override Response Processor
     func processNSOverrides(entries: [[String:AnyObject]]) {
         if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Process: Overrides") }
-        // because it's a small array, we're going to destroy and reload every time.
         overrideGraphData.removeAll()
-        for i in 0..<entries.count {
-            let currentEntry = entries[entries.count - 1 - i] as [String : AnyObject]?
-            var date: String
-            if currentEntry?["timestamp"] != nil {
-                date = currentEntry?["timestamp"] as! String
-            } else if currentEntry?["created_at"] != nil {
-                date = currentEntry?["created_at"] as! String
-            } else {
-                return
-            }
-            // Fix for FreeAPS milliseconds in timestamp
-            var strippedZone = String(date.dropLast())
-            strippedZone = strippedZone.components(separatedBy: ".")[0]
+        
+        entries.reversed().forEach { currentEntry in
+            guard let dateStr = currentEntry["timestamp"] as? String ?? currentEntry["created_at"] as? String else { return }
+            
+            guard let parsedDate = NightscoutUtils.parseDate(dateStr),
+                  let enteredBy = currentEntry["enteredBy"] as? String,
+                  let reason = currentEntry["reason"] as? String else { return }
             
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
-            dateFormatter.locale = Locale(identifier: "en_US")
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            let dateString = dateFormatter.date(from: strippedZone)
-            var dateTimeStamp = dateString!.timeIntervalSince1970
+            var dateTimeStamp = parsedDate.timeIntervalSince1970
             let graphHours = 24 * UserDefaultsRepository.downloadDays.value
             if dateTimeStamp < dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours) {
                 dateTimeStamp = dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours)
             }
             
-            var multiplier: Double = 1.0
-            if currentEntry?["insulinNeedsScaleFactor"] != nil {
-                multiplier = currentEntry?["insulinNeedsScaleFactor"] as! Double
-            }
-            var duration: Double = 5.0
-            if let durationType = currentEntry?["durationType"] as? String {
-                if i == entries.count - 1 {
-                    duration = dateTimeUtils.getNowTimeIntervalUTC() - dateTimeStamp + (60 * 60)
-                }
-            } else {
-                duration = (currentEntry?["duration"] as? Double)!
-                duration = duration * 60
-            }
+            let multiplier = currentEntry["insulinNeedsScaleFactor"] as? Double ?? 1.0
+            var duration = currentEntry["duration"] as? Double ?? 5.0
+            duration *= 60  // Convert duration to seconds
             
-            // Skip overrides that aren't 5 minutes long. This prevents overlapping that causes bars to not display.
-            if duration < 300 { continue }
-            
-            guard let enteredBy = currentEntry?["enteredBy"] as? String else { continue }
-            guard let reason = currentEntry?["reason"] as? String else { continue }
+            if duration < 300 { return }
             
             var range: [Int] = []
-            if let ranges = currentEntry?["correctionRange"] as? [Int] {
-                if ranges.count == 2 {
-                    guard let low = ranges[0] as? Int else { continue }
-                    guard let high = ranges[1] as? Int else { continue }
-                    range.append(low)
-                    range.append(high)
-                }
-                
+            if let ranges = currentEntry["correctionRange"] as? [Int], ranges.count == 2 {
+                range = ranges
             } else {
-                let low = currentEntry?["targetBottom"] as? Int
-                let high = currentEntry?["targetTop"] as? Int
-                
-                if (low == nil && high != nil) || (low != nil && high == nil) {
-                    continue
-                }
-                
-                if let l = low {
-                    range.append(l)
-                }
-                
-                if let h = high {
-                    range.append(h)
-                }
+                if let low = currentEntry["targetBottom"] as? Int, let high = currentEntry["targetTop"] as? Int {
+                    range = [low, high]
+                } else { return }
             }
             
-            let endDate = dateTimeStamp + (duration)
-            
+            let endDate = dateTimeStamp + duration
             let dot = DataStructs.overrideStruct(insulNeedsScaleFactor: multiplier, date: dateTimeStamp, endDate: endDate, duration: duration, correctionRange: range, enteredBy: enteredBy, reason: reason, sgv: -20)
             overrideGraphData.append(dot)
-            
-            
         }
+        
         if UserDefaultsRepository.graphOtherTreatments.value {
             updateOverrideGraph()
         }
-        
     }
 }

+ 8 - 21
LoopFollow/Controllers/Nightscout/Treatments/ResumePump.swift

@@ -11,42 +11,29 @@ extension MainViewController {
     // NS Resume Pump Response Processor
     func processResumePump(entries: [[String:AnyObject]]) {
         if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Process: Resume Pump") }
-        // because it's a small array, we're going to destroy and reload every time.
         resumeGraphData.removeAll()
+        
         var lastFoundIndex = 0
-        for i in 0..<entries.count {
-            let currentEntry = entries[entries.count - 1 - i] as [String : AnyObject]?
-            var date: String
-            if currentEntry?["timestamp"] != nil {
-                date = currentEntry?["timestamp"] as! String
-            } else if currentEntry?["created_at"] != nil {
-                date = currentEntry?["created_at"] as! String
-            } else {
+        
+        entries.reversed().forEach { currentEntry in
+            guard let dateStr = currentEntry["timestamp"] as? String ?? currentEntry["created_at"] as? String else { return }
+            
+            guard let parsedDate = NightscoutUtils.parseDate(dateStr) else {
                 return
             }
-            // Fix for FreeAPS milliseconds in timestamp
-            var strippedZone = String(date.dropLast())
-            strippedZone = strippedZone.components(separatedBy: ".")[0]
-            
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
-            dateFormatter.locale = Locale(identifier: "en_US")
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            let dateString = dateFormatter.date(from: strippedZone)
-            let dateTimeStamp = dateString!.timeIntervalSince1970
             
+            let dateTimeStamp = parsedDate.timeIntervalSince1970
             let sgv = findNearestBGbyTime(needle: dateTimeStamp, haystack: bgData, startingIndex: lastFoundIndex)
             lastFoundIndex = sgv.foundIndex
             
             if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
-                // Make the dot
                 let dot = DataStructs.timestampOnlyStruct(date: Double(dateTimeStamp), sgv: Int(sgv.sgv))
                 resumeGraphData.append(dot)
             }
         }
+        
         if UserDefaultsRepository.graphOtherTreatments.value {
             updateResumeGraph()
         }
-        
     }
 }

+ 11 - 16
LoopFollow/Controllers/Nightscout/Treatments/SensorStart.swift

@@ -24,23 +24,18 @@ extension MainViewController {
         var lastFoundIndex = 0
         for entry in entries {
             let date = entry.created_at
-            // Fix for FreeAPS milliseconds in timestamp
-            var strippedZone = String(date.dropLast())
-            strippedZone = strippedZone.components(separatedBy: ".")[0]
             
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
-            dateFormatter.locale = Locale(identifier: "en_US")
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            let dateString = dateFormatter.date(from: strippedZone)
-            let dateTimeStamp = dateString!.timeIntervalSince1970
-            
-            let sgv = findNearestBGbyTime(needle: dateTimeStamp, haystack: bgData, startingIndex: lastFoundIndex)
-            lastFoundIndex = sgv.foundIndex
-            
-            if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
-                let dot = DataStructs.timestampOnlyStruct(date: Double(dateTimeStamp), sgv: Int(sgv.sgv))
-                sensorStartGraphData.append(dot)
+            if let parsedDate = NightscoutUtils.parseDate(date) {
+                let dateTimeStamp = parsedDate.timeIntervalSince1970
+                let sgv = findNearestBGbyTime(needle: dateTimeStamp, haystack: bgData, startingIndex: lastFoundIndex)
+                lastFoundIndex = sgv.foundIndex
+                
+                if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
+                    let dot = DataStructs.timestampOnlyStruct(date: Double(dateTimeStamp), sgv: Int(sgv.sgv))
+                    sensorStartGraphData.append(dot)
+                }
+            } else {
+                print("Failed to parse date")
             }
         }
         if UserDefaultsRepository.graphOtherTreatments.value {

+ 8 - 20
LoopFollow/Controllers/Nightscout/Treatments/SuspendPump.swift

@@ -11,39 +11,27 @@ extension MainViewController {
     // NS Suspend Pump Response Processor
     func processSuspendPump(entries: [[String:AnyObject]]) {
         if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Process: Suspend Pump") }
-        // because it's a small array, we're going to destroy and reload every time.
         suspendGraphData.removeAll()
+        
         var lastFoundIndex = 0
-        for i in 0..<entries.count {
-            let currentEntry = entries[entries.count - 1 - i] as [String : AnyObject]?
-            var date: String
-            if currentEntry?["timestamp"] != nil {
-                date = currentEntry?["timestamp"] as! String
-            } else if currentEntry?["created_at"] != nil {
-                date = currentEntry?["created_at"] as! String
-            } else {
+        
+        entries.reversed().forEach { currentEntry in
+            guard let dateStr = currentEntry["timestamp"] as? String ?? currentEntry["created_at"] as? String else { return }
+            
+            guard let parsedDate = NightscoutUtils.parseDate(dateStr) else {
                 return
             }
-            // Fix for FreeAPS milliseconds in timestamp
-            var strippedZone = String(date.dropLast())
-            strippedZone = strippedZone.components(separatedBy: ".")[0]
-            
-            let dateFormatter = DateFormatter()
-            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
-            dateFormatter.locale = Locale(identifier: "en_US")
-            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
-            let dateString = dateFormatter.date(from: strippedZone)
-            let dateTimeStamp = dateString!.timeIntervalSince1970
             
+            let dateTimeStamp = parsedDate.timeIntervalSince1970
             let sgv = findNearestBGbyTime(needle: dateTimeStamp, haystack: bgData, startingIndex: lastFoundIndex)
             lastFoundIndex = sgv.foundIndex
             
             if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
-                // Make the dot
                 let dot = DataStructs.timestampOnlyStruct(date: Double(dateTimeStamp), sgv: Int(sgv.sgv))
                 suspendGraphData.append(dot)
             }
         }
+        
         if UserDefaultsRepository.graphOtherTreatments.value {
             updateSuspendGraph()
         }

+ 18 - 0
LoopFollow/helpers/NightscoutUtils.swift

@@ -183,4 +183,22 @@ class NightscoutUtils {
         }
         task.resume()
     }
+    
+    static func parseDate(_ dateString: String) -> Date? {
+        let dateFormatterWithMilliseconds = DateFormatter()
+        dateFormatterWithMilliseconds.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
+        dateFormatterWithMilliseconds.timeZone = TimeZone(abbreviation: "UTC")
+        
+        let dateFormatterWithoutMilliseconds = DateFormatter()
+        dateFormatterWithoutMilliseconds.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
+        dateFormatterWithoutMilliseconds.timeZone = TimeZone(abbreviation: "UTC")
+        
+        if let date = dateFormatterWithMilliseconds.date(from: dateString) {
+            return date
+        } else if let date = dateFormatterWithoutMilliseconds.date(from: dateString) {
+            return date
+        }
+        
+        return nil
+    }
 }