Skip to content

Commit

Permalink
feat: Updated target rates to support shifting evaluation period
Browse files Browse the repository at this point in the history
  • Loading branch information
BottlecapDave committed Mar 11, 2023
1 parent d40250d commit 6ac0a4e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 27 deletions.
59 changes: 36 additions & 23 deletions custom_components/carbon_intensity/binary_sensors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,48 @@
import math
from homeassistant.util.dt import (as_utc, parse_datetime)
from ..utils import (apply_offset)
import logging

_LOGGER = logging.getLogger(__name__)

def __get_applicable_rates(current_date, target_start_time, target_end_time, rates, target_start_offset, is_rolling_target):
if target_end_time != None:
# Get the target end for today. If this is in the past, then look at tomorrow
if (target_start_time is not None):
target_start = parse_datetime(current_date.strftime(f"%Y-%m-%dT{target_start_time}:00%z"))
else:
target_start = parse_datetime(current_date.strftime(f"%Y-%m-%dT00:00:00%z"))

if (target_end_time is not None):
target_end = parse_datetime(current_date.strftime(f"%Y-%m-%dT{target_end_time}:00%z"))
if (is_rolling_target == True and target_end < current_date):
target_end = target_end + timedelta(days=1)
else:
target_end = parse_datetime(current_date.strftime(f"%Y-%m-%dT00:00:00%z")) + timedelta(days=1)

if target_start_time != None:
# Get the target start on the same day as our target end. If this is after our target end (which can occur if we're looking for
# a time over night), then go back a day
target_start = parse_datetime(target_end.strftime(f"%Y-%m-%dT{target_start_time}:00%z"))
if (target_start > target_end):
target_start = target_start - timedelta(days=1)
target_start = as_utc(target_start)
target_end = as_utc(target_end)

elif target_end_time != None:
# If we have an end time set, then we should start from the same day as our end time
target_start = parse_datetime(target_end.strftime(f"%Y-%m-%dT00:00:00%z"))
elif is_rolling_target == False:
target_start = parse_datetime(current_date.strftime(f"%Y-%m-%dT00:00:00%z"))
else:
target_start = current_date
if (target_start >= target_end):
_LOGGER.debug(f'{target_start} is after {target_end}, so setting target end to tomorrow')
if target_start > current_date:
target_start = target_start - timedelta(days=1)
else:
target_end = target_end + timedelta(days=1)

# If our start date has passed, reset it to current_date to avoid picking a slot in the past
if (is_rolling_target == True and target_start < current_date):
if (is_rolling_target == True and target_start < current_date and current_date < target_end):
_LOGGER.debug(f'Rolling target and {target_start} is in the past. Setting start to {current_date}')
target_start = current_date

# Apply our offset so we make sure our target turns on within the specified timeframe
if (target_start_offset != None):
if (target_start_offset is not None):
_LOGGER.debug(f'Offsetting time period')
target_start = apply_offset(target_start, target_start_offset, True)
target_end = apply_offset(target_end, target_start_offset, True)

# Convert our target start/end timestamps to UTC as this is what our rates are in
target_start = as_utc(target_start)
if target_end is not None:
target_end = as_utc(target_end)
# If our start and end are both in the past, then look to the next day
if (target_start < current_date and target_end < current_date):
target_start = target_start + timedelta(days=1)
target_end = target_end + timedelta(days=1)

_LOGGER.debug(f'Finding rates between {target_start} and {target_end}')

# Retrieve the rates that are applicable for our target rate
applicable_rates = []
Expand All @@ -47,6 +52,14 @@ def __get_applicable_rates(current_date, target_start_time, target_end_time, rat
if rate["from"] >= target_start and (target_end == None or rate["to"] <= target_end):
applicable_rates.append(rate)

# Make sure that we have enough rates that meet our target period
date_diff = target_end - target_start
hours = (date_diff.days * 24) + (date_diff.seconds // 3600)
periods = hours * 2
if len(applicable_rates) < periods:
_LOGGER.debug(f'Incorrect number of periods discovered. Require {periods}, but only have {len(applicable_rates)}')
return None

return applicable_rates

def __get_intensity(rate):
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_calculate_continuous_times.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-10T11:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-09T11:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-09T11:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-09T11:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-10T11:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
# No start set
(datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T02:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T14:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-10T02:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T02:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T02:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T02:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-10T02:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
# No end set
(datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", None, datetime.strptime("2022-02-09T11:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", None, datetime.strptime("2022-02-09T14:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_calculate_intermittent_times.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-10T10:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-09T10:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-09T10:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-09T10:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", "18:00", datetime.strptime("2022-02-10T10:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
# # No start set
(datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-10T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
(datetime.strptime("2022-02-09T19:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), None, "18:00", datetime.strptime("2022-02-10T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), False),
# # No end set
(datetime.strptime("2022-02-09T00:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", None, datetime.strptime("2022-02-09T10:30:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
(datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), "10:00", None, datetime.strptime("2022-02-09T12:00:00Z", "%Y-%m-%dT%H:%M:%S%z"), True),
Expand Down

0 comments on commit 6ac0a4e

Please sign in to comment.