Skip to content

Commit

Permalink
fix(target-rate): Fixed issue with target rates not taking account of…
Browse files Browse the repository at this point in the history
… time zones
  • Loading branch information
BottlecapDave committed Sep 12, 2021
1 parent e8cc475 commit c68448f
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 22 deletions.
14 changes: 7 additions & 7 deletions custom_components/octopus_energy/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,29 @@ async def async_get_rates(self, product_code, tariff_code):
value_exc_vat = float(item["value_exc_vat"])
value_inc_vat = float(item["value_inc_vat"])

current_date = as_utc(parse_datetime(item["valid_from"]))
valid_from = as_utc(parse_datetime(item["valid_from"]))

# If we're on a fixed rate, then our current time could be in the past so we should go from
# our target period from date otherwise we could be adjusting times quite far in the past
if current_date < period_from:
current_date = period_from
if valid_from < period_from:
valid_from = period_from

# Some rates don't have end dates, so we should treat this as our period to target
if "valid_to" in item and item["valid_to"] != None:
target_date = as_utc(parse_datetime(item["valid_to"]))
else:
target_date = period_to

while current_date < target_date:
valid_to = current_date + timedelta(minutes=30)
while valid_from < target_date:
valid_to = valid_from + timedelta(minutes=30)
results.append({
"value_exc_vat": value_exc_vat,
"value_inc_vat": value_inc_vat,
"valid_from": current_date,
"valid_from": valid_from,
"valid_to": valid_to
})

current_date = valid_to
valid_from = valid_to

return results

Expand Down
35 changes: 20 additions & 15 deletions custom_components/octopus_energy/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging

from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.util.dt import (utcnow, as_utc, parse_datetime)
from homeassistant.util.dt import (utcnow, now, as_utc, parse_datetime)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity
)
Expand Down Expand Up @@ -80,17 +80,17 @@ def extra_state_attributes(self):
def is_on(self):
"""The state of the sensor."""

# Find the current rate.
# We only need to do this every half an hour
now = utcnow()
if (now.minute % 30) == 0 or len(self._target_rates) == 0:
# Find the current rate. Rates change a maximum of once every 30 minutes.
current_date = utcnow()
if (current_date.minute % 30) == 0 or len(self._target_rates) == 0:
_LOGGER.info(f'Updating OctopusEnergyTargetRate {self._config[CONFIG_TARGET_NAME]}')

# If all of our target times have passed, it's time to recalculate the next set
all_rates_in_past = True
for rate in self._target_rates:
if rate["valid_to"] > now:
if rate["valid_to"] > current_date:
all_rates_in_past = False
break

if all_rates_in_past:
if (self._config[CONFIG_TARGET_TYPE] == "Continuous"):
Expand All @@ -112,7 +112,7 @@ def is_on(self):
self._attributes = attributes

for rate in self._target_rates:
if now >= rate["valid_from"] and now <= rate["valid_to"]:
if current_date >= rate["valid_from"] and current_date <= rate["valid_to"]:
return True

return False
Expand All @@ -121,28 +121,33 @@ def get_valid_to(self, rate):
return rate["valid_to"]

def get_applicable_rates(self):
now = utcnow()
current_date = now()

if CONFIG_TARGET_END_TIME in self._config:
# Get the target end for today. If this is in the past, then look at tomorrow
target_end = as_utc(parse_datetime(now.strftime(f"%Y-%m-%dT{self._config[CONFIG_TARGET_END_TIME]}:%SZ")))
if (target_end < now):
target_end = parse_datetime(current_date.strftime(f"%Y-%m-%dT{self._config[CONFIG_TARGET_END_TIME]}:00%z"))
if (target_end < current_date):
target_end = target_end + timedelta(days=1)
else:
target_end = None

if CONFIG_TARGET_START_TIME in self._config:
# 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 = as_utc(parse_datetime(target_end.strftime(f"%Y-%m-%dT{self._config[CONFIG_TARGET_START_TIME]}:%SZ")))
target_start = parse_datetime(target_end.strftime(f"%Y-%m-%dT{self._config[CONFIG_TARGET_START_TIME]}:00%z"))
if (target_start > target_end):
target_start = target_start - timedelta(days=1)

# If our start date has passed, reset it to now to avoid picking a slot in the past
if (target_start < now):
target_start = now
# If our start date has passed, reset it to current_date to avoid picking a slot in the past
if (target_start < current_date):
target_start = current_date
else:
target_start = now
target_start = current_date

# 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)

# Retrieve the rates that are applicable for our target rate
rates = []
Expand Down

0 comments on commit c68448f

Please sign in to comment.