Skip to content

Commit

Permalink
Cache time zone from lat/lon results (#6)
Browse files Browse the repository at this point in the history
For time zone lookup, round lat/lon to 4 digits.
Ignore core_config_updated events without data.
  • Loading branch information
pnbruckner authored Feb 13, 2024
1 parent 4e48da1 commit da907ae
Showing 1 changed file with 21 additions and 5 deletions.
26 changes: 21 additions & 5 deletions custom_components/entity_tz/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from dataclasses import dataclass
from datetime import tzinfo
from enum import Enum, auto
from functools import lru_cache
import logging
from typing import Any, cast
from zoneinfo import available_timezones

Expand Down Expand Up @@ -45,6 +47,7 @@
from .nominatim import init_nominatim

_ALWAYS_DISABLED_ENTITIES = ("address", "country", "diff_country", "diff_time")
_LOGGER = logging.getLogger(__name__)


@dataclass(init=False)
Expand Down Expand Up @@ -72,6 +75,14 @@ def etz_data(hass: HomeAssistant) -> ETZData:
return cast(ETZData, hass.data[DOMAIN])


@lru_cache
def _get_tz_from_loc(tzf: TimezoneFinder, lat: float, lng: float) -> tzinfo | None:
"""Get time zone from a location."""
if (tz_name := tzf.timezone_at(lat=lat, lng=lng)) is None:
return None
return dt_util.get_time_zone(tz_name)


def get_tz(hass: HomeAssistant, state: State | None) -> tzinfo | str | None:
"""Get time zone from entity state."""
if not state:
Expand All @@ -82,10 +93,9 @@ def get_tz(hass: HomeAssistant, state: State | None) -> tzinfo | str | None:
lng = state.attributes.get(ATTR_LONGITUDE)
if lat is None or lng is None:
return STATE_UNAVAILABLE
tz_name = etz_data(hass).tzf.timezone_at(lat=lat, lng=lng)
if tz_name is None:
return None
return dt_util.get_time_zone(tz_name)
tz = _get_tz_from_loc(etz_data(hass).tzf, round(lat, 4), round(lng, 4))
_LOGGER.debug("Time zone cache: %s", _get_tz_from_loc.cache_info())
return tz


async def init_etz_data(hass: HomeAssistant) -> None:
Expand All @@ -108,8 +118,14 @@ def init_tz_data() -> None:

await hass.async_add_executor_job(init_tz_data)

async def update_zones(_: Event | None = None) -> None:
async def update_zones(event: Event | None = None) -> None:
"""Update list of zones to use."""
# Ignore events that do not contain any data.
# For some reason, there are two EVENT_CORE_CONFIG_UPDATE events issued at
# startup, even though the core config has not changed.
if event and not event.data:
return

zones = []
for state in hass.states.async_all(ZONE_DOMAIN):
if not_ha_tz(get_tz(hass, state)):
Expand Down

0 comments on commit da907ae

Please sign in to comment.