diff --git a/custom_components/tibber_prices/coordinator/period_handlers/period_building.py b/custom_components/tibber_prices/coordinator/period_handlers/period_building.py index 64c476a..0734e76 100644 --- a/custom_components/tibber_prices/coordinator/period_handlers/period_building.py +++ b/custom_components/tibber_prices/coordinator/period_handlers/period_building.py @@ -112,6 +112,19 @@ def build_periods( # noqa: PLR0913, PLR0915, PLR0912 - Complex period building intervals_filtered_by_flex = 0 intervals_filtered_by_min_distance = 0 + # Pre-compute criteria per day (flex/min_distance/reverse_sort are constant throughout; + # only ref_price and avg_price vary by day — max 3 entries: yesterday/today/tomorrow) + criteria_by_day: dict[date, TibberPricesIntervalCriteria] = { + day: TibberPricesIntervalCriteria( + ref_price=ref_prices[day], + avg_price=avg_prices[day], + flex=flex, + min_distance_from_avg=min_distance_from_avg, + reverse_sort=reverse_sort, + ) + for day in ref_prices + } + for price_data in all_prices: starts_at = time.get_interval_time(price_data) if starts_at is None: @@ -133,13 +146,7 @@ def build_periods( # noqa: PLR0913, PLR0915, PLR0912 - Complex period building ref_date = date_key # Check flex and minimum distance criteria (using smoothed price and interval's own day reference) - criteria = TibberPricesIntervalCriteria( - ref_price=ref_prices[ref_date], - avg_price=avg_prices[ref_date], - flex=flex, - min_distance_from_avg=min_distance_from_avg, - reverse_sort=reverse_sort, - ) + criteria = criteria_by_day[ref_date] in_flex, meets_min_distance = check_interval_criteria(price_for_criteria, criteria) # Track why intervals are filtered diff --git a/custom_components/tibber_prices/interval_pool/manager.py b/custom_components/tibber_prices/interval_pool/manager.py index 0dc525a..08dfaad 100644 --- a/custom_components/tibber_prices/interval_pool/manager.py +++ b/custom_components/tibber_prices/interval_pool/manager.py @@ -5,7 +5,7 @@ from __future__ import annotations import asyncio import contextlib import logging -from datetime import datetime, timedelta +from datetime import UTC, datetime, timedelta from typing import TYPE_CHECKING, Any from zoneinfo import ZoneInfo @@ -459,8 +459,6 @@ class TibberPricesIntervalPool: True if a real gap exists, False if the range is fully covered. """ - from datetime import UTC # noqa: PLC0415 - UTC constant needed here only - cached_intervals = self._get_cached_intervals(start_iso, end_iso) if not cached_intervals: @@ -582,14 +580,13 @@ class TibberPricesIntervalPool: resolution_change_naive = datetime(2025, 10, 1) # noqa: DTZ001 interval_minutes = INTERVAL_QUARTER_HOURLY if current_naive >= resolution_change_naive else INTERVAL_HOURLY + fetch_groups = self._cache.get_fetch_groups() while current_naive < end_naive: # Check if this timestamp exists in index (O(1) lookup) current_dt_key = current_naive.isoformat()[:19] location = self._index.get(current_dt_key) if location is not None: - # Get interval from fetch group - fetch_groups = self._cache.get_fetch_groups() fetch_group = fetch_groups[location["fetch_group_index"]] interval = fetch_group["intervals"][location["interval_index"]] # CRITICAL: Return shallow copy to prevent external mutations