diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift index 2319f4eceb..f5949c0f70 100644 --- a/Loop/Managers/LoopDataManager.swift +++ b/Loop/Managers/LoopDataManager.swift @@ -992,7 +992,7 @@ extension LoopDataManager { let retrospectiveStart = lastGlucoseDate.addingTimeInterval(-type(of: retrospectiveCorrection).retrospectionInterval) - let earliestEffectDate = Date(timeInterval: .hours(-24), since: now()) + let earliestEffectDate = Date(timeInterval: .hours(-48), since: now()) let nextCounteractionEffectDate = insulinCounteractionEffects.last?.endDate ?? earliestEffectDate let insulinEffectStartDate = nextCounteractionEffectDate.addingTimeInterval(.minutes(-5)) diff --git a/Loop/View Controllers/CarbAbsorptionViewController.swift b/Loop/View Controllers/CarbAbsorptionViewController.swift index fc770192e9..0a13c9b6ee 100644 --- a/Loop/View Controllers/CarbAbsorptionViewController.swift +++ b/Loop/View Controllers/CarbAbsorptionViewController.swift @@ -139,7 +139,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif charts.updateEndDate(chartStartDate.addingTimeInterval(.hours(totalHours+1))) // When there is no data, this allows presenting current hour + 1 let midnight = Calendar.current.startOfDay(for: Date()) - let listStart = min(midnight, chartStartDate, Date(timeIntervalSinceNow: -deviceManager.carbStore.maximumAbsorptionTimeInterval)) + let previousMidnight = midnight - .hours(24) let reloadGroup = DispatchGroup() let shouldUpdateGlucose = currentContext.contains(.glucose) @@ -158,11 +158,19 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif let allInsulinCounteractionEffects = state.insulinCounteractionEffects insulinCounteractionEffects = allInsulinCounteractionEffects.filterDateRange(chartStartDate, nil) + let earliestCounteractionEffect = allInsulinCounteractionEffects.first?.startDate ?? Date() + // Show carb entries as far back as previous midnight, or only as far back as counteraction effects are available + let boundOnCarbList = max(previousMidnight, earliestCounteractionEffect) + // If counteraction effects are missing, at least show all the entries for today and those on the chart + let displayListStart = min(boundOnCarbList, midnight, chartStartDate) + // To estimate dynamic carb absorption for the entry at the start of the list, we need to fetch samples that might still be absorbing + let fetchEntriesStart = displayListStart.addingTimeInterval(-self.deviceManager.carbStore.maximumAbsorptionTimeInterval) + reloadGroup.enter() - self.deviceManager.carbStore.getCarbStatus(start: listStart, end: nil, effectVelocities: allInsulinCounteractionEffects) { (result) in + self.deviceManager.carbStore.getCarbStatus(start: fetchEntriesStart, end: nil, effectVelocities: allInsulinCounteractionEffects) { (result) in switch result { case .success(let status): - carbStatuses = status + carbStatuses = status.filterDateRange(displayListStart, nil) carbsOnBoard = status.getClampedCarbsOnBoard() case .failure(let error): self.log.error("CarbStore failed to get carbStatus: %{public}@", String(describing: error)) @@ -287,6 +295,14 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif return formatter }() + private lazy var relativeTimeFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .medium + formatter.doesRelativeDateFormatting = true + formatter.timeStyle = .short + return formatter + }() + override func numberOfSections(in tableView: UITableView) -> Int { return Section.count } @@ -343,7 +359,14 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif } // Entry time - let startTime = timeFormatter.string(from: status.entry.startDate) + let startTime: String + // Indicate if an entry is from the previous day to avoid potential confusion + let midnight = Calendar.current.startOfDay(for: Date()) + if status.entry.startDate < midnight { + startTime = relativeTimeFormatter.string(from: status.entry.startDate) + } else { + startTime = timeFormatter.string(from: status.entry.startDate) + } if let absorptionTime = status.entry.absorptionTime, let duration = absorptionFormatter.string(from: absorptionTime) {