fix: sleep import groups segments by gap instead of date boundary
Problem: Segments crossing midnight were split into different nights - 22:30-23:15 (21.03) → assigned to 21.03 - 00:30-02:45 (22.03) → assigned to 22.03 But both belong to the same night (21/22.03)! Solution: Gap-based grouping - Sort segments chronologically - Group segments with gap < 2 hours - Night date = wake_time.date() (last segment's end date) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b1a92c01fc
commit
9a9c597187
|
|
@ -484,13 +484,20 @@ async def import_apple_health_sleep(
|
|||
'phase': phase_en
|
||||
})
|
||||
|
||||
# Group by night (wake date)
|
||||
nights = {}
|
||||
for seg in segments:
|
||||
wake_date = seg['end'].date() # Date of waking up
|
||||
# Sort segments chronologically
|
||||
segments.sort(key=lambda s: s['start'])
|
||||
|
||||
if wake_date not in nights:
|
||||
nights[wake_date] = {
|
||||
# Group segments into nights (gap-based)
|
||||
# If gap between segments > 2 hours → new night
|
||||
nights = []
|
||||
current_night = None
|
||||
|
||||
for seg in segments:
|
||||
# Start new night if:
|
||||
# 1. First segment
|
||||
# 2. Gap > 2 hours since last segment
|
||||
if current_night is None or (seg['start'] - current_night['wake_time']).total_seconds() > 7200:
|
||||
current_night = {
|
||||
'bedtime': seg['start'],
|
||||
'wake_time': seg['end'],
|
||||
'segments': [],
|
||||
|
|
@ -499,21 +506,28 @@ async def import_apple_health_sleep(
|
|||
'light_minutes': 0,
|
||||
'awake_minutes': 0
|
||||
}
|
||||
nights.append(current_night)
|
||||
|
||||
night = nights[wake_date]
|
||||
night['segments'].append(seg)
|
||||
night['wake_time'] = max(night['wake_time'], seg['end']) # Latest wake time
|
||||
night['bedtime'] = min(night['bedtime'], seg['start']) # Earliest bed time
|
||||
# Add segment to current night
|
||||
current_night['segments'].append(seg)
|
||||
current_night['wake_time'] = max(current_night['wake_time'], seg['end'])
|
||||
current_night['bedtime'] = min(current_night['bedtime'], seg['start'])
|
||||
|
||||
# Sum phases
|
||||
if seg['phase'] == 'deep':
|
||||
night['deep_minutes'] += seg['duration_min']
|
||||
current_night['deep_minutes'] += seg['duration_min']
|
||||
elif seg['phase'] == 'rem':
|
||||
night['rem_minutes'] += seg['duration_min']
|
||||
current_night['rem_minutes'] += seg['duration_min']
|
||||
elif seg['phase'] == 'light':
|
||||
night['light_minutes'] += seg['duration_min']
|
||||
current_night['light_minutes'] += seg['duration_min']
|
||||
elif seg['phase'] == 'awake':
|
||||
night['awake_minutes'] += seg['duration_min']
|
||||
current_night['awake_minutes'] += seg['duration_min']
|
||||
|
||||
# Convert nights list to dict with wake_date as key
|
||||
nights_dict = {}
|
||||
for night in nights:
|
||||
wake_date = night['wake_time'].date() # Date when you woke up
|
||||
nights_dict[wake_date] = night
|
||||
|
||||
# Insert nights
|
||||
imported = 0
|
||||
|
|
@ -522,7 +536,7 @@ async def import_apple_health_sleep(
|
|||
with get_db() as conn:
|
||||
cur = get_cursor(conn)
|
||||
|
||||
for date, night in nights.items():
|
||||
for date, night in nights_dict.items():
|
||||
# Calculate total duration (sum of all phases)
|
||||
duration_minutes = (
|
||||
night['deep_minutes'] +
|
||||
|
|
@ -593,6 +607,6 @@ async def import_apple_health_sleep(
|
|||
return {
|
||||
"imported": imported,
|
||||
"skipped": skipped,
|
||||
"total_nights": len(nights),
|
||||
"total_nights": len(nights_dict),
|
||||
"message": f"{imported} Nächte importiert, {skipped} übersprungen (manuelle Einträge)"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user