Fix blocking I/O in the event loop when loading timezones (#117721)

This commit is contained in:
J. Nick Koston 2024-05-19 23:06:03 -10:00 committed by GitHub
parent 0293315b23
commit 5a609c34bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
98 changed files with 294 additions and 217 deletions

View file

@ -309,7 +309,9 @@ class AmbientNetworkSensor(AmbientNetworkEntity, SensorEntity):
# Treatments for special units.
if value is not None and self.device_class == SensorDeviceClass.TIMESTAMP:
value = datetime.fromtimestamp(value / 1000, tz=dt_util.DEFAULT_TIME_ZONE)
value = datetime.fromtimestamp(
value / 1000, tz=dt_util.get_default_time_zone()
)
self._attr_available = value is not None
self._attr_native_value = value

View file

@ -196,7 +196,9 @@ class CalDavUpdateCoordinator(DataUpdateCoordinator[CalendarEvent | None]):
"""Return a datetime."""
if isinstance(obj, datetime):
return CalDavUpdateCoordinator.to_local(obj)
return datetime.combine(obj, time.min).replace(tzinfo=dt_util.DEFAULT_TIME_ZONE)
return datetime.combine(obj, time.min).replace(
tzinfo=dt_util.get_default_time_zone()
)
@staticmethod
def to_local(obj: datetime | date) -> datetime | date:

View file

@ -36,9 +36,7 @@ async def _async_set_value(entity: DateTimeEntity, service_call: ServiceCall) ->
"""Service call wrapper to set a new date/time."""
value: datetime = service_call.data[ATTR_DATETIME]
if value.tzinfo is None:
value = value.replace(
tzinfo=dt_util.get_time_zone(entity.hass.config.time_zone)
)
value = value.replace(tzinfo=dt_util.get_default_time_zone())
return await entity.async_set_value(value)

View file

@ -2,6 +2,7 @@
from __future__ import annotations
from datetime import tzinfo
import logging
from typing import Any
@ -29,12 +30,17 @@ async def async_setup_entry(
data: EcobeeData = hass.data[DOMAIN]
async_add_entities(
(
EcobeeVentilator20MinSwitch(data, index)
[
EcobeeVentilator20MinSwitch(
data,
index,
(await dt_util.async_get_time_zone(thermostat["location"]["timeZone"]))
or dt_util.get_default_time_zone(),
)
for index, thermostat in enumerate(data.ecobee.thermostats)
if thermostat["settings"]["ventilatorType"] != "none"
),
True,
],
update_before_add=True,
)
@ -48,15 +54,14 @@ class EcobeeVentilator20MinSwitch(EcobeeBaseEntity, SwitchEntity):
self,
data: EcobeeData,
thermostat_index: int,
operating_timezone: tzinfo,
) -> None:
"""Initialize ecobee ventilator platform."""
super().__init__(data, thermostat_index)
self._attr_unique_id = f"{self.base_unique_id}_ventilator_20m_timer"
self._attr_is_on = False
self.update_without_throttle = False
self._operating_timezone = dt_util.get_time_zone(
self.thermostat["location"]["timeZone"]
)
self._operating_timezone = operating_timezone
async def async_update(self) -> None:
"""Get the latest state from the thermostat."""

View file

@ -91,13 +91,13 @@ def _check_and_move_time(hop: Hop, time: str) -> datetime:
date_time = datetime.combine(
dt_util.start_of_local_day(),
datetime.strptime(time, "%I:%M %p").time(),
dt_util.DEFAULT_TIME_ZONE,
dt_util.get_default_time_zone(),
)
end_time = datetime.combine(
dt_util.start_of_local_day(),
datetime.strptime(hop.end.end_time, "%I:%M %p").time(),
dt_util.DEFAULT_TIME_ZONE,
dt_util.get_default_time_zone(),
)
if end_time < dt_util.now():

View file

@ -120,9 +120,7 @@ class GardenaBluetoothSensor(GardenaBluetoothDescriptorEntity, SensorEntity):
def _handle_coordinator_update(self) -> None:
value = self.coordinator.get_cached(self.entity_description.char)
if isinstance(value, datetime):
value = value.replace(
tzinfo=dt_util.get_time_zone(self.hass.config.time_zone)
)
value = value.replace(tzinfo=dt_util.get_default_time_zone())
self._attr_native_value = value
if char := self.entity_description.connected_state:

View file

@ -341,11 +341,11 @@ class GoogleCalendarEntity(
if isinstance(dtstart, datetime):
start = DateOrDatetime(
date_time=dt_util.as_local(dtstart),
timezone=str(dt_util.DEFAULT_TIME_ZONE),
timezone=str(dt_util.get_default_time_zone()),
)
end = DateOrDatetime(
date_time=dt_util.as_local(dtend),
timezone=str(dt_util.DEFAULT_TIME_ZONE),
timezone=str(dt_util.get_default_time_zone()),
)
else:
start = DateOrDatetime(date=dtstart)

View file

@ -38,7 +38,7 @@ def _truncate_timeline(timeline: Timeline, max_events: int) -> Timeline:
truncated = list(itertools.islice(upcoming, max_events))
return Timeline(
[
SortableItemValue(event.timespan_of(dt_util.DEFAULT_TIME_ZONE), event)
SortableItemValue(event.timespan_of(dt_util.get_default_time_zone()), event)
for event in truncated
]
)
@ -73,7 +73,7 @@ class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
raise UpdateFailed(f"Error communicating with API: {err}") from err
timeline = await self.sync.store_service.async_get_timeline(
dt_util.DEFAULT_TIME_ZONE
dt_util.get_default_time_zone()
)
self._upcoming_timeline = _truncate_timeline(timeline, MAX_UPCOMING_EVENTS)
return timeline

View file

@ -45,7 +45,7 @@ async def async_get_config_entry_diagnostics(
"""Return diagnostics for a config entry."""
payload: dict[str, Any] = {
"now": dt_util.now().isoformat(),
"timezone": str(dt_util.DEFAULT_TIME_ZONE),
"timezone": str(dt_util.get_default_time_zone()),
"system_timezone": str(datetime.datetime.now().astimezone().tzinfo),
}

View file

@ -239,7 +239,7 @@ class GrowattData:
date_now = dt_util.now().date()
last_updated_time = dt_util.parse_time(str(sorted_keys[-1]))
mix_detail["lastdataupdate"] = datetime.datetime.combine(
date_now, last_updated_time, dt_util.DEFAULT_TIME_ZONE
date_now, last_updated_time, dt_util.get_default_time_zone()
)
# Dashboard data is largely inaccurate for mix system but it is the only

View file

@ -119,7 +119,7 @@ async def async_attach_trigger(
hour,
minute,
second,
tzinfo=dt_util.DEFAULT_TIME_ZONE,
tzinfo=dt_util.get_default_time_zone(),
)
# Only set up listener if time is now or in the future.
if trigger_dt >= dt_util.now():

View file

@ -237,11 +237,11 @@ class InputDatetime(collection.CollectionEntity, RestoreEntity):
# If the user passed in an initial value with a timezone, convert it to right tz
if current_datetime.tzinfo is not None:
self._current_datetime = current_datetime.astimezone(
dt_util.DEFAULT_TIME_ZONE
dt_util.get_default_time_zone()
)
else:
self._current_datetime = current_datetime.replace(
tzinfo=dt_util.DEFAULT_TIME_ZONE
tzinfo=dt_util.get_default_time_zone()
)
@classmethod
@ -295,7 +295,7 @@ class InputDatetime(collection.CollectionEntity, RestoreEntity):
)
self._current_datetime = current_datetime.replace(
tzinfo=dt_util.DEFAULT_TIME_ZONE
tzinfo=dt_util.get_default_time_zone()
)
@property
@ -409,7 +409,7 @@ class InputDatetime(collection.CollectionEntity, RestoreEntity):
time = self._current_datetime.time()
self._current_datetime = py_datetime.datetime.combine(
date, time, dt_util.DEFAULT_TIME_ZONE
date, time, dt_util.get_default_time_zone()
)
self.async_write_ha_state()

View file

@ -80,7 +80,7 @@ class KNXDateTime(KnxEntity, DateTimeEntity, RestoreEntity):
):
self._device.remote_value.value = (
datetime.fromisoformat(last_state.state)
.astimezone(dt_util.DEFAULT_TIME_ZONE)
.astimezone(dt_util.get_default_time_zone())
.timetuple()
)
@ -96,9 +96,11 @@ class KNXDateTime(KnxEntity, DateTimeEntity, RestoreEntity):
hour=time_struct.tm_hour,
minute=time_struct.tm_min,
second=min(time_struct.tm_sec, 59), # account for leap seconds
tzinfo=dt_util.DEFAULT_TIME_ZONE,
tzinfo=dt_util.get_default_time_zone(),
)
async def async_set_value(self, value: datetime) -> None:
"""Change the value."""
await self._device.set(value.astimezone(dt_util.DEFAULT_TIME_ZONE).timetuple())
await self._device.set(
value.astimezone(dt_util.get_default_time_zone()).timetuple()
)

View file

@ -45,7 +45,7 @@ LITTER_ROBOT_3_SLEEP_START = RobotTimeEntityDescription[LitterRobot3](
entity_category=EntityCategory.CONFIG,
value_fn=lambda robot: _as_local_time(robot.sleep_mode_start_time),
set_fn=lambda robot, value: robot.set_sleep_mode(
robot.sleep_mode_enabled, value.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE)
robot.sleep_mode_enabled, value.replace(tzinfo=dt_util.get_default_time_zone())
),
)

View file

@ -18,7 +18,7 @@ async def async_get_config_entry_diagnostics(
"""Return diagnostics for a config entry."""
payload: dict[str, Any] = {
"now": dt_util.now().isoformat(),
"timezone": str(dt_util.DEFAULT_TIME_ZONE),
"timezone": str(dt_util.get_default_time_zone()),
"system_timezone": str(datetime.datetime.now().astimezone().tzinfo),
}
store = hass.data[DOMAIN][config_entry.entry_id]

View file

@ -134,7 +134,7 @@ class LocalTodoListEntity(TodoListEntity):
self._attr_unique_id = unique_id
def _new_todo_store(self) -> TodoStore:
return TodoStore(self._calendar, tzinfo=dt_util.DEFAULT_TIME_ZONE)
return TodoStore(self._calendar, tzinfo=dt_util.get_default_time_zone())
async def async_update(self) -> None:
"""Update entity state based on the local To-do items."""

View file

@ -80,7 +80,7 @@ class MetWeatherData:
if not resp:
raise CannotConnect
self.current_weather_data = self._weather_data.get_current_weather()
time_zone = dt_util.DEFAULT_TIME_ZONE
time_zone = dt_util.get_default_time_zone()
self.daily_forecast = self._weather_data.get_forecast(time_zone, False, 0)
self.hourly_forecast = self._weather_data.get_forecast(time_zone, True)
return self

View file

@ -86,7 +86,7 @@ class MetEireannWeatherData:
"""Fetch data from API - (current weather and forecast)."""
await self._weather_data.fetching_data()
self.current_weather_data = self._weather_data.get_current_weather()
time_zone = dt_util.DEFAULT_TIME_ZONE
time_zone = dt_util.get_default_time_zone()
self.daily_forecast = self._weather_data.get_forecast(time_zone, False)
self.hourly_forecast = self._weather_data.get_forecast(time_zone, True)
return self

View file

@ -25,7 +25,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
ip=ip_address,
discover=discover,
synchronous=False,
timezone=dt_util.DEFAULT_TIME_ZONE,
timezone=dt_util.get_default_time_zone(),
)
await hub.connect()

View file

@ -251,13 +251,13 @@ class ONVIFDevice:
LOGGER.debug("%s: Device time: %s", self.name, device_time)
tzone = dt_util.DEFAULT_TIME_ZONE
tzone = dt_util.get_default_time_zone()
cdate = device_time.LocalDateTime
if device_time.UTCDateTime:
tzone = dt_util.UTC
cdate = device_time.UTCDateTime
elif device_time.TimeZone:
tzone = dt_util.get_time_zone(device_time.TimeZone.TZ) or tzone
tzone = await dt_util.async_get_time_zone(device_time.TimeZone.TZ) or tzone
if cdate is None:
LOGGER.warning("%s: Could not retrieve date/time on this camera", self.name)

View file

@ -73,7 +73,7 @@ class RainBirdCalendarEntity(
schedule = self.coordinator.data
if not schedule:
return None
cursor = schedule.timeline_tz(dt_util.DEFAULT_TIME_ZONE).active_after(
cursor = schedule.timeline_tz(dt_util.get_default_time_zone()).active_after(
dt_util.now()
)
program_event = next(cursor, None)

View file

@ -952,7 +952,7 @@ def reduce_day_ts_factory() -> (
# We have to recreate _local_from_timestamp in the closure in case the timezone changes
_local_from_timestamp = partial(
datetime.fromtimestamp, tz=dt_util.DEFAULT_TIME_ZONE
datetime.fromtimestamp, tz=dt_util.get_default_time_zone()
)
def _same_day_ts(time1: float, time2: float) -> bool:
@ -1000,7 +1000,7 @@ def reduce_week_ts_factory() -> (
# We have to recreate _local_from_timestamp in the closure in case the timezone changes
_local_from_timestamp = partial(
datetime.fromtimestamp, tz=dt_util.DEFAULT_TIME_ZONE
datetime.fromtimestamp, tz=dt_util.get_default_time_zone()
)
def _same_week_ts(time1: float, time2: float) -> bool:
@ -1058,7 +1058,7 @@ def reduce_month_ts_factory() -> (
# We have to recreate _local_from_timestamp in the closure in case the timezone changes
_local_from_timestamp = partial(
datetime.fromtimestamp, tz=dt_util.DEFAULT_TIME_ZONE
datetime.fromtimestamp, tz=dt_util.get_default_time_zone()
)
def _same_month_ts(time1: float, time2: float) -> bool:

View file

@ -115,7 +115,7 @@ class RiscoSensor(CoordinatorEntity[RiscoEventsDataUpdateCoordinator], SensorEnt
return None
if res := dt_util.parse_datetime(self._event.time):
return res.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE)
return res.replace(tzinfo=dt_util.get_default_time_zone())
return None
@property

View file

@ -10,6 +10,8 @@ from homeassistant.util.dt import get_time_zone
from .const import DOMAIN, LOGGER
EUROPE_AMSTERDAM_ZONE_INFO = get_time_zone("Europe/Amsterdam")
class RovaCoordinator(DataUpdateCoordinator[dict[str, datetime]]):
"""Class to manage fetching Rova data."""
@ -33,7 +35,7 @@ class RovaCoordinator(DataUpdateCoordinator[dict[str, datetime]]):
for item in items:
date = datetime.strptime(item["Date"], "%Y-%m-%dT%H:%M:%S").replace(
tzinfo=get_time_zone("Europe/Amsterdam")
tzinfo=EUROPE_AMSTERDAM_ZONE_INFO
)
code = item["GarbageTypeCode"].lower()
if code not in data:

View file

@ -15,6 +15,7 @@ from homeassistant.util import dt as dt_util
from .const import DOMAIN, LOGGER, MIN_TIME_BETWEEN_UPDATES, PHOENIX_TIME_ZONE
TIMEOUT = 10
PHOENIX_ZONE_INFO = dt_util.get_time_zone(PHOENIX_TIME_ZONE)
class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]):
@ -43,8 +44,7 @@ class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]):
"""
LOGGER.debug("async_update_data enter")
# Fetch srp_energy data
phx_time_zone = dt_util.get_time_zone(PHOENIX_TIME_ZONE)
end_date = dt_util.now(phx_time_zone)
end_date = dt_util.now(PHOENIX_ZONE_INFO)
start_date = end_date - timedelta(days=1)
try:
async with asyncio.timeout(TIMEOUT):

View file

@ -42,7 +42,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
tibber_connection = tibber.Tibber(
access_token=entry.data[CONF_ACCESS_TOKEN],
websession=async_get_clientsession(hass),
time_zone=dt_util.DEFAULT_TIME_ZONE,
time_zone=dt_util.get_default_time_zone(),
)
hass.data[DOMAIN] = tibber_connection

View file

@ -148,7 +148,7 @@ class TodSensor(BinarySensorEntity):
assert self._time_after is not None
assert self._time_before is not None
assert self._next_update is not None
if time_zone := dt_util.get_time_zone(self.hass.config.time_zone):
if time_zone := dt_util.get_default_time_zone():
return {
ATTR_AFTER: self._time_after.astimezone(time_zone).isoformat(),
ATTR_BEFORE: self._time_before.astimezone(time_zone).isoformat(),
@ -160,9 +160,7 @@ class TodSensor(BinarySensorEntity):
"""Convert naive time from config to utc_datetime with current day."""
# get the current local date from utc time
current_local_date = (
dt_util.utcnow()
.astimezone(dt_util.get_time_zone(self.hass.config.time_zone))
.date()
dt_util.utcnow().astimezone(dt_util.get_default_time_zone()).date()
)
# calculate utc datetime corresponding to local time
return dt_util.as_utc(datetime.combine(current_local_date, naive_time))

View file

@ -77,7 +77,7 @@ class TVDataUpdateCoordinator(DataUpdateCoordinator):
datetime.combine(
departure_day,
self._time,
dt_util.get_time_zone(self.hass.config.time_zone),
dt_util.get_default_time_zone(),
)
if self._time
else dt_util.now()

View file

@ -87,7 +87,7 @@ async def validate_input(
when = datetime.combine(
departure_day,
_time,
dt_util.get_time_zone(hass.config.time_zone),
dt_util.get_default_time_zone(),
)
try:

View file

@ -105,7 +105,7 @@ class TVDataUpdateCoordinator(DataUpdateCoordinator[TrainData]):
when = datetime.combine(
departure_day,
self._time,
dt_util.get_time_zone(self.hass.config.time_zone),
dt_util.get_default_time_zone(),
)
try:
if self._time:

View file

@ -670,7 +670,7 @@ class ProtectMediaSource(MediaSource):
hour=0,
minute=0,
second=0,
tzinfo=dt_util.DEFAULT_TIME_ZONE,
tzinfo=dt_util.get_default_time_zone(),
)
if is_all:
if start_dt.month < 12:

View file

@ -566,7 +566,7 @@ class UtilityMeterSensor(RestoreSensor):
async def _program_reset(self):
"""Program the reset of the utility meter."""
if self._cron_pattern is not None:
tz = dt_util.get_time_zone(self.hass.config.time_zone)
tz = dt_util.get_default_time_zone()
self._next_reset = croniter(self._cron_pattern, dt_util.now(tz)).get_next(
datetime
) # we need timezone for DST purposes (see issue #102984)

View file

@ -109,7 +109,7 @@ class ValloxFilterRemainingSensor(ValloxSensorEntity):
return datetime.combine(
next_filter_change_date,
time(hour=13, minute=0, second=0, tzinfo=dt_util.DEFAULT_TIME_ZONE),
time(hour=13, minute=0, second=0, tzinfo=dt_util.get_default_time_zone()),
)

View file

@ -910,7 +910,7 @@ async def async_process_ha_core_config(hass: HomeAssistant, config: dict) -> Non
_raise_issue_if_no_country(hass, hass.config.country)
if CONF_TIME_ZONE in config:
hac.set_time_zone(config[CONF_TIME_ZONE])
await hac.async_set_time_zone(config[CONF_TIME_ZONE])
if CONF_MEDIA_DIRS not in config:
if is_docker_env():

View file

@ -2951,16 +2951,38 @@ class Config:
"debug": self.debug,
}
def set_time_zone(self, time_zone_str: str) -> None:
async def async_set_time_zone(self, time_zone_str: str) -> None:
"""Help to set the time zone."""
if time_zone := await dt_util.async_get_time_zone(time_zone_str):
self.time_zone = time_zone_str
dt_util.set_default_time_zone(time_zone)
else:
raise ValueError(f"Received invalid time zone {time_zone_str}")
def set_time_zone(self, time_zone_str: str) -> None:
"""Set the time zone.
This is a legacy method that should not be used in new code.
Use async_set_time_zone instead.
It will be removed in Home Assistant 2025.6.
"""
# report is imported here to avoid a circular import
from .helpers.frame import report # pylint: disable=import-outside-toplevel
report(
"set the time zone using set_time_zone instead of async_set_time_zone"
" which will stop working in Home Assistant 2025.6",
error_if_core=True,
error_if_integration=True,
)
if time_zone := dt_util.get_time_zone(time_zone_str):
self.time_zone = time_zone_str
dt_util.set_default_time_zone(time_zone)
else:
raise ValueError(f"Received invalid time zone {time_zone_str}")
@callback
def _update(
async def _async_update(
self,
*,
source: ConfigSource,
@ -2993,7 +3015,7 @@ class Config:
if location_name is not None:
self.location_name = location_name
if time_zone is not None:
self.set_time_zone(time_zone)
await self.async_set_time_zone(time_zone)
if external_url is not _UNDEF:
self.external_url = cast(str | None, external_url)
if internal_url is not _UNDEF:
@ -3013,7 +3035,7 @@ class Config:
_raise_issue_if_no_country,
)
self._update(source=ConfigSource.STORAGE, **kwargs)
await self._async_update(source=ConfigSource.STORAGE, **kwargs)
await self._async_store()
self.hass.bus.async_fire_internal(EVENT_CORE_CONFIG_UPDATE, kwargs)
@ -3039,7 +3061,7 @@ class Config:
):
_LOGGER.warning("Invalid internal_url set. It's not allowed to have a path")
self._update(
await self._async_update(
source=ConfigSource.STORAGE,
latitude=data.get("latitude"),
longitude=data.get("longitude"),

View file

@ -8,6 +8,7 @@ aiohttp-fast-zlib==0.1.0
aiohttp==3.9.5
aiohttp_cors==0.7.0
aiohttp_session==2.12.0
aiozoneinfo==0.1.0
astral==2.2
async-interrupt==1.1.1
async-upnp-client==0.38.3

View file

@ -5,11 +5,12 @@ from __future__ import annotations
import bisect
from contextlib import suppress
import datetime as dt
from functools import partial
from functools import lru_cache, partial
import re
from typing import Any, Literal, overload
import zoneinfo
from aiozoneinfo import async_get_time_zone as _async_get_time_zone
import ciso8601
DATE_STR_FORMAT = "%Y-%m-%d"
@ -74,6 +75,12 @@ POSTGRES_INTERVAL_RE = re.compile(
)
@lru_cache(maxsize=1)
def get_default_time_zone() -> dt.tzinfo:
"""Get the default time zone."""
return DEFAULT_TIME_ZONE
def set_default_time_zone(time_zone: dt.tzinfo) -> None:
"""Set a default time zone to be used when none is specified.
@ -85,12 +92,14 @@ def set_default_time_zone(time_zone: dt.tzinfo) -> None:
assert isinstance(time_zone, dt.tzinfo)
DEFAULT_TIME_ZONE = time_zone
get_default_time_zone.cache_clear()
def get_time_zone(time_zone_str: str) -> dt.tzinfo | None:
"""Get time zone from string. Return None if unable to determine.
Async friendly.
Must be run in the executor if the ZoneInfo is not already
in the cache. If you are not sure, use async_get_time_zone.
"""
try:
return zoneinfo.ZoneInfo(time_zone_str)
@ -98,6 +107,17 @@ def get_time_zone(time_zone_str: str) -> dt.tzinfo | None:
return None
async def async_get_time_zone(time_zone_str: str) -> dt.tzinfo | None:
"""Get time zone from string. Return None if unable to determine.
Async friendly.
"""
try:
return await _async_get_time_zone(time_zone_str)
except zoneinfo.ZoneInfoNotFoundError:
return None
# We use a partial here since it is implemented in native code
# and avoids the global lookup of UTC
utcnow = partial(dt.datetime.now, UTC)

View file

@ -29,6 +29,7 @@ dependencies = [
"aiohttp_session==2.12.0",
"aiohttp-fast-url-dispatcher==0.3.0",
"aiohttp-fast-zlib==0.1.0",
"aiozoneinfo==0.1.0",
"astral==2.2",
"async-interrupt==1.1.1",
"attrs==23.2.0",

View file

@ -9,6 +9,7 @@ aiohttp_cors==0.7.0
aiohttp_session==2.12.0
aiohttp-fast-url-dispatcher==0.3.0
aiohttp-fast-zlib==0.1.0
aiozoneinfo==0.1.0
astral==2.2
async-interrupt==1.1.1
attrs==23.2.0

View file

@ -232,7 +232,7 @@ async def async_test_home_assistant(
orig_async_add_job = hass.async_add_job
orig_async_add_executor_job = hass.async_add_executor_job
orig_async_create_task_internal = hass.async_create_task_internal
orig_tz = dt_util.DEFAULT_TIME_ZONE
orig_tz = dt_util.get_default_time_zone()
def async_add_job(target, *args, eager_start: bool = False):
"""Add job."""
@ -279,7 +279,7 @@ async def async_test_home_assistant(
hass.config.latitude = 32.87336
hass.config.longitude = -117.22743
hass.config.elevation = 0
hass.config.set_time_zone("US/Pacific")
await hass.config.async_set_time_zone("US/Pacific")
hass.config.units = METRIC_SYSTEM
hass.config.media_dirs = {"local": get_test_config_dir("media")}
hass.config.skip_pip = True
@ -361,7 +361,7 @@ async def async_test_home_assistant(
yield hass
# Restore timezone, it is set when creating the hass object
dt_util.DEFAULT_TIME_ZONE = orig_tz
dt_util.set_default_time_zone(orig_tz)
def async_mock_service(

View file

@ -71,7 +71,7 @@ async def test_form_options(
) -> None:
"""Test the form options."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
with patch(
"homeassistant.components.aemet.AEMET.api_call",
@ -112,7 +112,7 @@ async def test_form_duplicated_id(
) -> None:
"""Test setting up duplicated entry."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
with patch(
"homeassistant.components.aemet.AEMET.api_call",

View file

@ -20,7 +20,7 @@ async def test_coordinator_error(
) -> None:
"""Test error on coordinator update."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass)

View file

@ -28,7 +28,7 @@ async def test_unload_entry(
) -> None:
"""Test (un)loading the AEMET integration."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
with patch(
"homeassistant.components.aemet.AEMET.api_call",
@ -54,7 +54,7 @@ async def test_init_town_not_found(
) -> None:
"""Test TownNotFound when loading the AEMET integration."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
with patch(
"homeassistant.components.aemet.AEMET.api_call",
@ -80,7 +80,7 @@ async def test_init_api_timeout(
) -> None:
"""Test API timeouts when loading the AEMET integration."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
with patch(
"homeassistant.components.aemet.AEMET.api_call",

View file

@ -15,7 +15,7 @@ async def test_aemet_forecast_create_sensors(
) -> None:
"""Test creation of forecast sensors."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass)
@ -76,7 +76,7 @@ async def test_aemet_weather_create_sensors(
) -> None:
"""Test creation of weather sensors."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass)

View file

@ -35,7 +35,7 @@ async def test_aemet_weather(
) -> None:
"""Test states of the weather."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass)
@ -69,7 +69,7 @@ async def test_forecast_service(
) -> None:
"""Test multiple forecast."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass)
@ -109,7 +109,7 @@ async def test_forecast_subscription(
"""Test multiple forecast."""
client = await hass_ws_client(hass)
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass)

View file

@ -315,10 +315,10 @@ def mock_tz() -> str | None:
@pytest.fixture(autouse=True)
def set_tz(hass: HomeAssistant, tz: str | None) -> None:
async def set_tz(hass: HomeAssistant, tz: str | None) -> None:
"""Fixture to set the default TZ to the one requested."""
if tz is not None:
hass.config.set_time_zone(tz)
await hass.config.async_set_time_zone(tz)
@pytest.fixture(autouse=True)
@ -721,7 +721,7 @@ async def test_all_day_event(
target_datetime: datetime.datetime,
) -> None:
"""Test that the event lasting the whole day is returned, if it's early in the local day."""
freezer.move_to(target_datetime.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE))
freezer.move_to(target_datetime.replace(tzinfo=dt_util.get_default_time_zone()))
assert await async_setup_component(
hass,
"calendar",
@ -895,7 +895,7 @@ async def test_event_rrule_all_day_early(
target_datetime: datetime.datetime,
) -> None:
"""Test that the recurring all day event is returned early in the local day, and not on the first occurrence."""
freezer.move_to(target_datetime.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE))
freezer.move_to(target_datetime.replace(tzinfo=dt_util.get_default_time_zone()))
assert await async_setup_component(
hass,
"calendar",

View file

@ -91,9 +91,9 @@ def platforms() -> list[Platform]:
@pytest.fixture(autouse=True)
def set_tz(hass: HomeAssistant) -> None:
async def set_tz(hass: HomeAssistant) -> None:
"""Fixture to set timezone with fixed offset year round."""
hass.config.set_time_zone("America/Regina")
await hass.config.async_set_time_zone("America/Regina")
@pytest.fixture(name="todos")

View file

@ -28,11 +28,11 @@ TEST_DOMAIN = "test"
@pytest.fixture
def set_time_zone(hass: HomeAssistant) -> None:
async def set_time_zone(hass: HomeAssistant) -> None:
"""Set the time zone for the tests."""
# Set our timezone to CST/Regina so we can check calculations
# This keeps UTC-6 all year round
hass.config.set_time_zone("America/Regina")
await hass.config.async_set_time_zone("America/Regina")
class MockFlow(ConfigFlow):

View file

@ -700,8 +700,8 @@ async def test_event_start_trigger_dst(
freezer: FrozenDateTimeFactory,
) -> None:
"""Test a calendar event trigger happening at the start of daylight savings time."""
await hass.config.async_set_time_zone("America/Los_Angeles")
tzinfo = zoneinfo.ZoneInfo("America/Los_Angeles")
hass.config.set_time_zone("America/Los_Angeles")
freezer.move_to("2023-03-12 01:00:00-08:00")
# Before DST transition starts

View file

@ -18,7 +18,7 @@ DEFAULT_VALUE = datetime(2020, 1, 1, 12, 0, 0, tzinfo=UTC)
async def test_datetime(hass: HomeAssistant) -> None:
"""Test date/time entity."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
setup_test_component_platform(
hass,
DOMAIN,

View file

@ -37,7 +37,7 @@ def test_setup_params(hass: HomeAssistant) -> None:
async def test_set_datetime(hass: HomeAssistant) -> None:
"""Test set datetime service."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
await hass.services.async_call(
DOMAIN,
SERVICE_SET_VALUE,

View file

@ -24,7 +24,7 @@ from .conftest import ComponentSetup, YieldFixture
from tests.common import MockConfigEntry
DEFAULT_TIME_ZONE = dt_util.DEFAULT_TIME_ZONE
DEFAULT_TIME_ZONE = dt_util.get_default_time_zone()
TEST_TZ_NAME = "Pacific/Auckland"
TEST_TIMEZONE = zoneinfo.ZoneInfo(TEST_TZ_NAME)

View file

@ -28,9 +28,9 @@ from tests.components.light.common import MockLight
@pytest.fixture(autouse=True)
def set_utc(hass):
async def set_utc(hass):
"""Set timezone to UTC."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
async def test_valid_config(hass: HomeAssistant) -> None:

View file

@ -67,7 +67,7 @@ def mock_forecast_solar(hass) -> Generator[None, MagicMock, None]:
autospec=True,
) as forecast_solar_mock:
forecast_solar = forecast_solar_mock.return_value
now = datetime(2021, 6, 27, 6, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE)
now = datetime(2021, 6, 27, 6, 0, tzinfo=dt_util.get_default_time_zone())
estimate = MagicMock(spec=models.Estimate)
estimate.now.return_value = now
@ -79,10 +79,10 @@ def mock_forecast_solar(hass) -> Generator[None, MagicMock, None]:
estimate.energy_production_tomorrow = 200000
estimate.power_production_now = 300000
estimate.power_highest_peak_time_today = datetime(
2021, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE
2021, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()
)
estimate.power_highest_peak_time_tomorrow = datetime(
2021, 6, 27, 14, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE
2021, 6, 27, 14, 0, tzinfo=dt_util.get_default_time_zone()
)
estimate.energy_current_hour = 800000
@ -96,16 +96,16 @@ def mock_forecast_solar(hass) -> Generator[None, MagicMock, None]:
1: 900000,
}.get
estimate.watts = {
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 10,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 100,
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 10,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 100,
}
estimate.wh_days = {
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 20,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 200,
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 20,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 200,
}
estimate.wh_period = {
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 30,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 300,
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 30,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 300,
}
forecast_solar.estimate.return_value = estimate

View file

@ -330,11 +330,11 @@ def mock_insert_event(
@pytest.fixture(autouse=True)
def set_time_zone(hass):
async def set_time_zone(hass):
"""Set the time zone for the tests."""
# Set our timezone to CST/Regina so we can check calculations
# This keeps UTC-6 all year round
hass.config.set_time_zone("America/Regina")
await hass.config.async_set_time_zone("America/Regina")
@pytest.fixture

View file

@ -474,7 +474,7 @@ async def test_http_api_event(
component_setup,
) -> None:
"""Test querying the API and fetching events from the server."""
hass.config.set_time_zone("Asia/Baghdad")
await hass.config.async_set_time_zone("Asia/Baghdad")
event = {
**TEST_EVENT,
**upcoming(),
@ -788,7 +788,7 @@ async def test_all_day_iter_order(
event_order,
) -> None:
"""Test the sort order of an all day events depending on the time zone."""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
mock_events_list_items(
[
{

View file

@ -781,7 +781,7 @@ async def test_history_during_period_significant_domain(
time_zone,
) -> None:
"""Test history_during_period with climate domain."""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
now = dt_util.utcnow()
await async_setup_component(hass, "history", {})

View file

@ -241,7 +241,7 @@ async def test_history_during_period_significant_domain(
time_zone,
) -> None:
"""Test history_during_period with climate domain."""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
now = dt_util.utcnow()
await async_setup_component(hass, "history", {})

View file

@ -591,7 +591,7 @@ async def test_async_start_from_history_and_switch_to_watching_state_changes_sin
hass: HomeAssistant,
) -> None:
"""Test we startup from history and switch to watching state changes."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0)
@ -692,7 +692,7 @@ async def test_async_start_from_history_and_switch_to_watching_state_changes_sin
hass: HomeAssistant,
) -> None:
"""Test we startup from history and switch to watching state changes with an expanding end time."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0)
@ -809,7 +809,7 @@ async def test_async_start_from_history_and_switch_to_watching_state_changes_mul
hass: HomeAssistant,
) -> None:
"""Test we startup from history and switch to watching state changes."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0)
@ -950,7 +950,7 @@ async def test_does_not_work_into_the_future(
Verifies we do not regress https://github.com/home-assistant/core/pull/20589
"""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0)
@ -1357,7 +1357,7 @@ async def test_measure_from_end_going_backwards(
async def test_measure_cet(recorder_mock: Recorder, hass: HomeAssistant) -> None:
"""Test the history statistics sensor measure with a non-UTC timezone."""
hass.config.set_time_zone("Europe/Berlin")
await hass.config.async_set_time_zone("Europe/Berlin")
start_time = dt_util.utcnow() - timedelta(minutes=60)
t0 = start_time + timedelta(minutes=20)
t1 = t0 + timedelta(minutes=10)
@ -1446,7 +1446,7 @@ async def test_end_time_with_microseconds_zeroed(
hass: HomeAssistant,
) -> None:
"""Test the history statistics sensor that has the end time microseconds zeroed out."""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
start_of_today = dt_util.now().replace(
day=9, month=7, year=1986, hour=0, minute=0, second=0, microsecond=0
)
@ -1650,7 +1650,7 @@ async def test_history_stats_handles_floored_timestamps(
hass: HomeAssistant,
) -> None:
"""Test we account for microseconds when doing the data calculation."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0)
last_times = None

View file

@ -688,7 +688,7 @@ async def test_setup_no_config(hass: HomeAssistant, hass_admin_user: MockUser) -
async def test_timestamp(hass: HomeAssistant) -> None:
"""Test timestamp."""
hass.config.set_time_zone("America/Los_Angeles")
await hass.config.async_set_time_zone("America/Los_Angeles")
assert await async_setup_component(
hass,

View file

@ -21,9 +21,9 @@ from tests.common import MockConfigEntry, async_fire_time_changed
@pytest.fixture(autouse=True)
def set_utc(hass: HomeAssistant) -> None:
async def set_utc(hass: HomeAssistant) -> None:
"""Set timezone to UTC."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
async def test_successful_config_entry(hass: HomeAssistant) -> None:

View file

@ -15,9 +15,9 @@ from tests.common import MockConfigEntry
@pytest.fixture(autouse=True)
def set_utc(hass: HomeAssistant) -> None:
async def set_utc(hass: HomeAssistant) -> None:
"""Set timezone to UTC."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
@pytest.mark.parametrize(

View file

@ -184,7 +184,7 @@ async def test_issur_melacha_sensor(
time_zone = dt_util.get_time_zone(tzname)
test_time = now.replace(tzinfo=time_zone)
hass.config.set_time_zone(tzname)
await hass.config.async_set_time_zone(tzname)
hass.config.latitude = latitude
hass.config.longitude = longitude
@ -272,7 +272,7 @@ async def test_issur_melacha_sensor_update(
time_zone = dt_util.get_time_zone(tzname)
test_time = now.replace(tzinfo=time_zone)
hass.config.set_time_zone(tzname)
await hass.config.async_set_time_zone(tzname)
hass.config.latitude = latitude
hass.config.longitude = longitude

View file

@ -167,7 +167,7 @@ async def test_jewish_calendar_sensor(
time_zone = dt_util.get_time_zone(tzname)
test_time = now.replace(tzinfo=time_zone)
hass.config.set_time_zone(tzname)
await hass.config.async_set_time_zone(tzname)
hass.config.latitude = latitude
hass.config.longitude = longitude
@ -512,7 +512,7 @@ async def test_shabbat_times_sensor(
time_zone = dt_util.get_time_zone(tzname)
test_time = now.replace(tzinfo=time_zone)
hass.config.set_time_zone(tzname)
await hass.config.async_set_time_zone(tzname)
hass.config.latitude = latitude
hass.config.longitude = longitude

View file

@ -50,7 +50,7 @@ async def test_datetime(hass: HomeAssistant, knx: KNXTestKit) -> None:
async def test_date_restore_and_respond(hass: HomeAssistant, knx: KNXTestKit) -> None:
"""Test KNX datetime with passive_address, restoring state and respond_to_read."""
hass.config.set_time_zone("Europe/Vienna")
await hass.config.async_set_time_zone("Europe/Vienna")
test_address = "1/1/1"
test_passive_address = "3/3/3"
fake_state = State("datetime.test", "2022-03-03T03:04:05+00:00")

View file

@ -33,7 +33,7 @@ async def test_calendar_events(
) -> None:
"""Test the calendar."""
test_time = datetime(2024, 1, 12, 11, tzinfo=dt_util.DEFAULT_TIME_ZONE)
test_time = datetime(2024, 1, 12, 11, tzinfo=dt_util.get_default_time_zone())
freezer.move_to(test_time)
await async_init_integration(hass, mock_config_entry)
@ -86,8 +86,8 @@ async def test_calendar_edge_cases(
end_date: datetime,
) -> None:
"""Test edge cases."""
start_date = start_date.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE)
end_date = end_date.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE)
start_date = start_date.replace(tzinfo=dt_util.get_default_time_zone())
end_date = end_date.replace(tzinfo=dt_util.get_default_time_zone())
# set schedule to be only on Sunday, 07:00 - 07:30
mock_lamarzocco.schedule[2]["enable"] = "Disabled"
@ -124,7 +124,7 @@ async def test_no_calendar_events_global_disable(
"""Assert no events when global auto on/off is disabled."""
mock_lamarzocco.current_status["global_auto"] = "Disabled"
test_time = datetime(2024, 1, 12, 11, tzinfo=dt_util.DEFAULT_TIME_ZONE)
test_time = datetime(2024, 1, 12, 11, tzinfo=dt_util.get_default_time_zone())
freezer.move_to(test_time)
await async_init_integration(hass, mock_config_entry)

View file

@ -87,11 +87,11 @@ def mock_time_zone() -> str:
@pytest.fixture(autouse=True)
def set_time_zone(hass: HomeAssistant, time_zone: str):
async def set_time_zone(hass: HomeAssistant, time_zone: str):
"""Set the time zone for the tests."""
# Set our timezone to CST/Regina so we can check calculations
# This keeps UTC-6 all year round
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
@pytest.fixture(name="config_entry")

View file

@ -61,9 +61,9 @@ async def ws_move_item(
@pytest.fixture(autouse=True)
def set_time_zone(hass: HomeAssistant) -> None:
async def set_time_zone(hass: HomeAssistant) -> None:
"""Set the time zone for the tests that keesp UTC-6 all year round."""
hass.config.set_time_zone("America/Regina")
await hass.config.async_set_time_zone("America/Regina")
EXPECTED_ADD_ITEM = {

View file

@ -68,9 +68,9 @@ async def hass_(recorder_mock, hass):
@pytest.fixture
def set_utc(hass):
async def set_utc(hass):
"""Set timezone to UTC."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
async def test_service_call_create_logbook_entry(hass_) -> None:

View file

@ -47,9 +47,9 @@ from tests.typing import RecorderInstanceGenerator, WebSocketGenerator
@pytest.fixture
def set_utc(hass):
async def set_utc(hass):
"""Set timezone to UTC."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
def listeners_without_writes(listeners: dict[str, int]) -> dict[str, int]:

View file

@ -39,7 +39,7 @@ async def test_sensor(
freezer: FrozenDateTimeFactory,
) -> None:
"""Test states of the air_quality."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2024-04-20 12:00:00+00:00")
with patch("homeassistant.components.nam.PLATFORMS", [Platform.SENSOR]):

View file

@ -42,7 +42,7 @@ async def test_config_flow(
- Configure options to introduce API Token, with bad auth and good one
"""
freezer.move_to(_MOCK_TIME_VALID_RESPONSES)
hass.config.set_time_zone("Europe/Madrid")
await hass.config.async_set_time_zone("Europe/Madrid")
tst_config = {
CONF_NAME: "test",
ATTR_TARIFF: TARIFFS[1],
@ -184,7 +184,7 @@ async def test_reauth(
) -> None:
"""Test reauth flow for API-token mode."""
freezer.move_to(_MOCK_TIME_BAD_AUTH_RESPONSES)
hass.config.set_time_zone("Europe/Madrid")
await hass.config.async_set_time_zone("Europe/Madrid")
tst_config = {
CONF_NAME: "test",
ATTR_TARIFF: TARIFFS[1],

View file

@ -91,9 +91,9 @@ async def setup_config_entry(
@pytest.fixture(autouse=True)
def set_time_zone(hass: HomeAssistant):
async def set_time_zone(hass: HomeAssistant):
"""Set the time zone for the tests."""
hass.config.set_time_zone("America/Regina")
await hass.config.async_set_time_zone("America/Regina")
@pytest.fixture(autouse=True)

View file

@ -602,7 +602,7 @@ async def test_get_significant_states_with_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)

View file

@ -382,7 +382,7 @@ async def test_get_significant_states_with_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)

View file

@ -604,7 +604,7 @@ async def test_get_significant_states_with_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)

View file

@ -1027,7 +1027,7 @@ async def run_tasks_at_time(hass: HomeAssistant, test_time: datetime) -> None:
async def test_auto_purge(hass: HomeAssistant, setup_recorder: None) -> None:
"""Test periodic purge scheduling."""
timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
tz = dt_util.get_time_zone(timezone)
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by
@ -1089,7 +1089,7 @@ async def test_auto_purge_auto_repack_on_second_sunday(
) -> None:
"""Test periodic purge scheduling does a repack on the 2nd sunday."""
timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
tz = dt_util.get_time_zone(timezone)
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by
@ -1132,7 +1132,7 @@ async def test_auto_purge_auto_repack_disabled_on_second_sunday(
) -> None:
"""Test periodic purge scheduling does not auto repack on the 2nd sunday if disabled."""
timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
await async_setup_recorder_instance(hass, {CONF_AUTO_REPACK: False})
tz = dt_util.get_time_zone(timezone)
@ -1176,7 +1176,7 @@ async def test_auto_purge_no_auto_repack_on_not_second_sunday(
) -> None:
"""Test periodic purge scheduling does not do a repack unless its the 2nd sunday."""
timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
tz = dt_util.get_time_zone(timezone)
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by
@ -1220,7 +1220,7 @@ async def test_auto_purge_disabled(
) -> None:
"""Test periodic db cleanup still run when auto purge is disabled."""
timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
await async_setup_recorder_instance(hass, {CONF_AUTO_PURGE: False})
tz = dt_util.get_time_zone(timezone)
@ -1262,7 +1262,7 @@ async def test_auto_statistics(
) -> None:
"""Test periodic statistics scheduling."""
timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
tz = dt_util.get_time_zone(timezone)
stats_5min = []

View file

@ -361,9 +361,9 @@ async def test_lazy_state_handles_same_last_updated_and_last_changed(
@pytest.mark.parametrize(
"time_zone", ["Europe/Berlin", "America/Chicago", "US/Hawaii", "UTC"]
)
def test_process_datetime_to_timestamp(time_zone, hass: HomeAssistant) -> None:
async def test_process_datetime_to_timestamp(time_zone, hass: HomeAssistant) -> None:
"""Test we can handle processing database datatimes to timestamps."""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
utc_now = dt_util.utcnow()
assert process_datetime_to_timestamp(utc_now) == utc_now.timestamp()
now = dt_util.now()
@ -373,14 +373,14 @@ def test_process_datetime_to_timestamp(time_zone, hass: HomeAssistant) -> None:
@pytest.mark.parametrize(
"time_zone", ["Europe/Berlin", "America/Chicago", "US/Hawaii", "UTC"]
)
def test_process_datetime_to_timestamp_freeze_time(
async def test_process_datetime_to_timestamp_freeze_time(
time_zone, hass: HomeAssistant
) -> None:
"""Test we can handle processing database datatimes to timestamps.
This test freezes time to make sure everything matches.
"""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
utc_now = dt_util.utcnow()
with freeze_time(utc_now):
epoch = utc_now.timestamp()
@ -396,7 +396,7 @@ async def test_process_datetime_to_timestamp_mirrors_utc_isoformat_behavior(
time_zone, hass: HomeAssistant
) -> None:
"""Test process_datetime_to_timestamp mirrors process_timestamp_to_utc_isoformat."""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
datetime_with_tzinfo = datetime(2016, 7, 9, 11, 0, 0, tzinfo=dt_util.UTC)
datetime_without_tzinfo = datetime(2016, 7, 9, 11, 0, 0)
est = dt_util.get_time_zone("US/Eastern")

View file

@ -1102,7 +1102,7 @@ async def test_daily_statistics_sum(
timezone,
) -> None:
"""Test daily statistics."""
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text
@ -1282,7 +1282,7 @@ async def test_weekly_statistics_mean(
timezone,
) -> None:
"""Test weekly statistics."""
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text
@ -1417,7 +1417,7 @@ async def test_weekly_statistics_sum(
timezone,
) -> None:
"""Test weekly statistics."""
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text
@ -1597,7 +1597,7 @@ async def test_monthly_statistics_sum(
timezone,
) -> None:
"""Test monthly statistics."""
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text
@ -1917,7 +1917,7 @@ async def test_change(
timezone,
) -> None:
"""Test deriving change from sum statistic."""
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text
@ -2256,7 +2256,7 @@ async def test_change_with_none(
This tests the behavior when some record has None sum. The calculated change
is not expected to be correct, but we should not raise on this error.
"""
hass.config.set_time_zone(timezone)
await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text

View file

@ -1127,7 +1127,7 @@ async def test_statistics_during_period_in_the_past(
recorder_mock: Recorder, hass: HomeAssistant, hass_ws_client: WebSocketGenerator
) -> None:
"""Test statistics_during_period in the past."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
now = dt_util.utcnow().replace()
hass.config.units = US_CUSTOMARY_SYSTEM

View file

@ -32,7 +32,7 @@ async def test_control_event(
snapshot: SnapshotAssertion,
) -> None:
"""Test event update updates correct event object."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
await setup_rfx_test_cfg(
@ -60,7 +60,7 @@ async def test_status_event(
snapshot: SnapshotAssertion,
) -> None:
"""Test event update updates correct event object."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
await setup_rfx_test_cfg(

View file

@ -97,7 +97,7 @@ async def test_only_chime_devices(
caplog,
) -> None:
"""Tests the update service works correctly if only chimes are returned."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
requests_mock.get(
"https://api.ring.com/clients_api/ring_devices",

View file

@ -158,8 +158,8 @@ def _check_state(hass, category, entity_id):
@pytest.fixture
def _set_utc_time_zone(hass):
hass.config.set_time_zone("UTC")
async def _set_utc_time_zone(hass):
await hass.config.async_set_time_zone("UTC")
@pytest.fixture

View file

@ -20,11 +20,11 @@ from tests.common import MockConfigEntry
@pytest.fixture(name="setup_hass_config", autouse=True)
def fixture_setup_hass_config(hass: HomeAssistant) -> None:
async def fixture_setup_hass_config(hass: HomeAssistant) -> None:
"""Set up things to be run when tests are started."""
hass.config.latitude = 33.27
hass.config.longitude = 112
hass.config.set_time_zone(PHOENIX_TIME_ZONE)
await hass.config.async_set_time_zone(PHOENIX_TIME_ZONE)
@pytest.fixture(name="hass_tz_info")

View file

@ -51,7 +51,7 @@ async def test_intervals(
tracked_time,
) -> None:
"""Test timing intervals of sensors when time zone is UTC."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
freezer.move_to(start_time)
await load_int(hass, display_option)
@ -61,7 +61,7 @@ async def test_intervals(
async def test_states(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> None:
"""Test states of sensors."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
now = dt_util.utc_from_timestamp(1495068856)
freezer.move_to(now)
@ -121,7 +121,7 @@ async def test_states_non_default_timezone(
hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None:
"""Test states of sensors in a timezone other than UTC."""
hass.config.set_time_zone("America/New_York")
await hass.config.async_set_time_zone("America/New_York")
now = dt_util.utc_from_timestamp(1495068856)
freezer.move_to(now)
@ -254,7 +254,7 @@ async def test_timezone_intervals(
tracked_time,
) -> None:
"""Test timing intervals of sensors in timezone other than UTC."""
hass.config.set_time_zone(time_zone)
await hass.config.async_set_time_zone(time_zone)
freezer.move_to(start_time)
await load_int(hass, "date")

View file

@ -22,11 +22,11 @@ def hass_time_zone():
@pytest.fixture(autouse=True)
def setup_fixture(hass, hass_time_zone):
async def setup_fixture(hass, hass_time_zone):
"""Set up things to be run when tests are started."""
hass.config.latitude = 50.27583
hass.config.longitude = 18.98583
hass.config.set_time_zone(hass_time_zone)
await hass.config.async_set_time_zone(hass_time_zone)
@pytest.fixture

View file

@ -113,9 +113,9 @@ def mock_setup_integration(hass: HomeAssistant) -> None:
@pytest.fixture(autouse=True)
def set_time_zone(hass: HomeAssistant) -> None:
async def set_time_zone(hass: HomeAssistant) -> None:
"""Set the time zone for the tests that keesp UTC-6 all year round."""
hass.config.set_time_zone("America/Regina")
await hass.config.async_set_time_zone("America/Regina")
async def create_mock_platform(

View file

@ -42,9 +42,9 @@ def platforms() -> list[Platform]:
@pytest.fixture(autouse=True)
def set_time_zone(hass: HomeAssistant):
async def set_time_zone(hass: HomeAssistant):
"""Set the time zone for the tests."""
hass.config.set_time_zone(TZ_NAME)
await hass.config.async_set_time_zone(TZ_NAME)
def get_events_url(entity: str, start: str, end: str) -> str:

View file

@ -23,9 +23,9 @@ def platforms() -> list[Platform]:
@pytest.fixture(autouse=True)
def set_time_zone(hass: HomeAssistant) -> None:
async def set_time_zone(hass: HomeAssistant) -> None:
"""Set the time zone for the tests that keesp UTC-6 all year round."""
hass.config.set_time_zone("America/Regina")
await hass.config.async_set_time_zone("America/Regina")
@pytest.mark.parametrize(

View file

@ -55,9 +55,9 @@ from tests.common import (
@pytest.fixture(autouse=True)
def set_utc(hass: HomeAssistant):
async def set_utc(hass: HomeAssistant):
"""Set timezone to UTC."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
@pytest.mark.parametrize(

View file

@ -18,21 +18,21 @@ def set_tz(request):
@pytest.fixture
def utc(hass: HomeAssistant) -> None:
async def utc(hass: HomeAssistant) -> None:
"""Set the default TZ to UTC."""
hass.config.set_time_zone("UTC")
hass.config.async_set_time_zone("UTC")
@pytest.fixture
def helsinki(hass: HomeAssistant) -> None:
async def helsinki(hass: HomeAssistant) -> None:
"""Set the default TZ to Europe/Helsinki."""
hass.config.set_time_zone("Europe/Helsinki")
hass.config.async_set_time_zone("Europe/Helsinki")
@pytest.fixture
def new_york(hass: HomeAssistant) -> None:
async def new_york(hass: HomeAssistant) -> None:
"""Set the default TZ to America/New_York."""
hass.config.set_time_zone("America/New_York")
hass.config.async_set_time_zone("America/New_York")
def _sensor_to_datetime(sensor):

View file

@ -44,7 +44,7 @@ async def test_zodiac_day(
hass: HomeAssistant, now: datetime, sign: str, element: str, modality: str
) -> None:
"""Test the zodiac sensor."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
MockConfigEntry(
domain=DOMAIN,
).add_to_hass(hass)

View file

@ -1455,7 +1455,9 @@ def hass_recorder(
) -> HomeAssistant:
"""Set up with params."""
if timezone is not None:
hass.config.set_time_zone(timezone)
asyncio.run_coroutine_threadsafe(
hass.config.async_set_time_zone(timezone), hass.loop
).result()
init_recorder_component(hass, config, recorder_db_url)
hass.start()
hass.block_till_done()

View file

@ -3059,7 +3059,7 @@ async def test_if_action_before_sunrise_no_offset_kotzebue(
at 7 AM and sunset at 3AM during summer
After sunrise is true from sunrise until midnight, local time.
"""
hass.config.set_time_zone("America/Anchorage")
await hass.config.async_set_time_zone("America/Anchorage")
hass.config.latitude = 66.5
hass.config.longitude = 162.4
await async_setup_component(
@ -3136,7 +3136,7 @@ async def test_if_action_after_sunrise_no_offset_kotzebue(
at 7 AM and sunset at 3AM during summer
Before sunrise is true from midnight until sunrise, local time.
"""
hass.config.set_time_zone("America/Anchorage")
await hass.config.async_set_time_zone("America/Anchorage")
hass.config.latitude = 66.5
hass.config.longitude = 162.4
await async_setup_component(
@ -3213,7 +3213,7 @@ async def test_if_action_before_sunset_no_offset_kotzebue(
at 7 AM and sunset at 3AM during summer
Before sunset is true from midnight until sunset, local time.
"""
hass.config.set_time_zone("America/Anchorage")
await hass.config.async_set_time_zone("America/Anchorage")
hass.config.latitude = 66.5
hass.config.longitude = 162.4
await async_setup_component(
@ -3290,7 +3290,7 @@ async def test_if_action_after_sunset_no_offset_kotzebue(
at 7 AM and sunset at 3AM during summer
After sunset is true from sunset until midnight, local time.
"""
hass.config.set_time_zone("America/Anchorage")
await hass.config.async_set_time_zone("America/Anchorage")
hass.config.latitude = 66.5
hass.config.longitude = 162.4
await async_setup_component(

View file

@ -49,7 +49,7 @@ import homeassistant.util.dt as dt_util
from tests.common import async_fire_time_changed, async_fire_time_changed_exact
DEFAULT_TIME_ZONE = dt_util.DEFAULT_TIME_ZONE
DEFAULT_TIME_ZONE = dt_util.get_default_time_zone()
async def test_track_point_in_time(hass: HomeAssistant) -> None:
@ -4097,7 +4097,7 @@ async def test_periodic_task_entering_dst(
hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None:
"""Test periodic task behavior when entering dst."""
hass.config.set_time_zone("Europe/Vienna")
await hass.config.async_set_time_zone("Europe/Vienna")
specific_runs = []
today = date.today().isoformat()
@ -4148,7 +4148,7 @@ async def test_periodic_task_entering_dst_2(
This tests a task firing every second in the range 0..58 (not *:*:59)
"""
hass.config.set_time_zone("Europe/Vienna")
await hass.config.async_set_time_zone("Europe/Vienna")
specific_runs = []
today = date.today().isoformat()
@ -4198,7 +4198,7 @@ async def test_periodic_task_leaving_dst(
hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None:
"""Test periodic task behavior when leaving dst."""
hass.config.set_time_zone("Europe/Vienna")
await hass.config.async_set_time_zone("Europe/Vienna")
specific_runs = []
today = date.today().isoformat()
@ -4274,7 +4274,7 @@ async def test_periodic_task_leaving_dst_2(
hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None:
"""Test periodic task behavior when leaving dst."""
hass.config.set_time_zone("Europe/Vienna")
await hass.config.async_set_time_zone("Europe/Vienna")
specific_runs = []
today = date.today().isoformat()
@ -4565,7 +4565,7 @@ async def test_async_track_point_in_time_cancel(hass: HomeAssistant) -> None:
"""Test cancel of async track point in time."""
times = []
hass.config.set_time_zone("US/Hawaii")
await hass.config.async_set_time_zone("US/Hawaii")
hst_tz = dt_util.get_time_zone("US/Hawaii")
@ha.callback

View file

@ -1108,9 +1108,9 @@ def test_strptime(hass: HomeAssistant) -> None:
assert render(hass, "{{ strptime('invalid', '%Y', default=1) }}") == 1
def test_timestamp_custom(hass: HomeAssistant) -> None:
async def test_timestamp_custom(hass: HomeAssistant) -> None:
"""Test the timestamps to custom filter."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
now = dt_util.utcnow()
tests = [
(1469119144, None, True, "2016-07-21 16:39:04"),
@ -1150,9 +1150,9 @@ def test_timestamp_custom(hass: HomeAssistant) -> None:
assert render(hass, "{{ None | timestamp_custom(default=1) }}") == 1
def test_timestamp_local(hass: HomeAssistant) -> None:
async def test_timestamp_local(hass: HomeAssistant) -> None:
"""Test the timestamps to local filter."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
tests = [
(1469119144, "2016-07-21T16:39:04+00:00"),
]
@ -2225,14 +2225,14 @@ def test_utcnow(mock_is_safe, hass: HomeAssistant) -> None:
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True,
)
def test_today_at(
async def test_today_at(
mock_is_safe, hass: HomeAssistant, now, expected, expected_midnight, timezone_str
) -> None:
"""Test today_at method."""
freezer = freeze_time(now)
freezer.start()
hass.config.set_time_zone(timezone_str)
await hass.config.async_set_time_zone(timezone_str)
result = template.Template(
"{{ today_at('10:00').isoformat() }}",
@ -2273,9 +2273,9 @@ def test_today_at(
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True,
)
def test_relative_time(mock_is_safe, hass: HomeAssistant) -> None:
async def test_relative_time(mock_is_safe, hass: HomeAssistant) -> None:
"""Test relative_time method."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
relative_time_template = (
'{{relative_time(strptime("2000-01-01 09:00:00", "%Y-%m-%d %H:%M:%S"))}}'
@ -2380,9 +2380,9 @@ def test_relative_time(mock_is_safe, hass: HomeAssistant) -> None:
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True,
)
def test_time_since(mock_is_safe, hass: HomeAssistant) -> None:
async def test_time_since(mock_is_safe, hass: HomeAssistant) -> None:
"""Test time_since method."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
time_since_template = (
'{{time_since(strptime("2000-01-01 09:00:00", "%Y-%m-%d %H:%M:%S"))}}'
@ -2543,9 +2543,9 @@ def test_time_since(mock_is_safe, hass: HomeAssistant) -> None:
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True,
)
def test_time_until(mock_is_safe, hass: HomeAssistant) -> None:
async def test_time_until(mock_is_safe, hass: HomeAssistant) -> None:
"""Test time_until method."""
hass.config.set_time_zone("UTC")
await hass.config.async_set_time_zone("UTC")
now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
time_until_template = (
'{{time_until(strptime("2000-01-01 11:00:00", "%Y-%m-%d %H:%M:%S"))}}'

View file

@ -3502,3 +3502,16 @@ async def test_thread_safety_message(hass: HomeAssistant) -> None:
),
):
await hass.async_add_executor_job(hass.verify_event_loop_thread, "test")
async def test_set_time_zone_deprecated(hass: HomeAssistant) -> None:
"""Test set_time_zone is deprecated."""
with pytest.raises(
RuntimeError,
match=re.escape(
"Detected code that set the time zone using set_time_zone instead of "
"async_set_time_zone which will stop working in Home Assistant 2025.6. "
"Please report this issue.",
),
):
await hass.config.set_time_zone("America/New_York")

View file

@ -8,7 +8,7 @@ import pytest
import homeassistant.util.dt as dt_util
DEFAULT_TIME_ZONE = dt_util.DEFAULT_TIME_ZONE
DEFAULT_TIME_ZONE = dt_util.get_default_time_zone()
TEST_TIME_ZONE = "America/Los_Angeles"
@ -25,11 +25,21 @@ def test_get_time_zone_retrieves_valid_time_zone() -> None:
assert dt_util.get_time_zone(TEST_TIME_ZONE) is not None
async def test_async_get_time_zone_retrieves_valid_time_zone() -> None:
"""Test getting a time zone."""
assert await dt_util.async_get_time_zone(TEST_TIME_ZONE) is not None
def test_get_time_zone_returns_none_for_garbage_time_zone() -> None:
"""Test getting a non existing time zone."""
assert dt_util.get_time_zone("Non existing time zone") is None
async def test_async_get_time_zone_returns_none_for_garbage_time_zone() -> None:
"""Test getting a non existing time zone."""
assert await dt_util.async_get_time_zone("Non existing time zone") is None
def test_set_default_time_zone() -> None:
"""Test setting default time zone."""
time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)