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. # Treatments for special units.
if value is not None and self.device_class == SensorDeviceClass.TIMESTAMP: 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_available = value is not None
self._attr_native_value = value self._attr_native_value = value

View File

@ -196,7 +196,9 @@ class CalDavUpdateCoordinator(DataUpdateCoordinator[CalendarEvent | None]):
"""Return a datetime.""" """Return a datetime."""
if isinstance(obj, datetime): if isinstance(obj, datetime):
return CalDavUpdateCoordinator.to_local(obj) 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 @staticmethod
def to_local(obj: datetime | date) -> datetime | date: 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.""" """Service call wrapper to set a new date/time."""
value: datetime = service_call.data[ATTR_DATETIME] value: datetime = service_call.data[ATTR_DATETIME]
if value.tzinfo is None: if value.tzinfo is None:
value = value.replace( value = value.replace(tzinfo=dt_util.get_default_time_zone())
tzinfo=dt_util.get_time_zone(entity.hass.config.time_zone)
)
return await entity.async_set_value(value) return await entity.async_set_value(value)

View File

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

View File

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

View File

@ -341,11 +341,11 @@ class GoogleCalendarEntity(
if isinstance(dtstart, datetime): if isinstance(dtstart, datetime):
start = DateOrDatetime( start = DateOrDatetime(
date_time=dt_util.as_local(dtstart), date_time=dt_util.as_local(dtstart),
timezone=str(dt_util.DEFAULT_TIME_ZONE), timezone=str(dt_util.get_default_time_zone()),
) )
end = DateOrDatetime( end = DateOrDatetime(
date_time=dt_util.as_local(dtend), date_time=dt_util.as_local(dtend),
timezone=str(dt_util.DEFAULT_TIME_ZONE), timezone=str(dt_util.get_default_time_zone()),
) )
else: else:
start = DateOrDatetime(date=dtstart) 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)) truncated = list(itertools.islice(upcoming, max_events))
return Timeline( 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 for event in truncated
] ]
) )
@ -73,7 +73,7 @@ class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
raise UpdateFailed(f"Error communicating with API: {err}") from err raise UpdateFailed(f"Error communicating with API: {err}") from err
timeline = await self.sync.store_service.async_get_timeline( 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) self._upcoming_timeline = _truncate_timeline(timeline, MAX_UPCOMING_EVENTS)
return timeline return timeline

View File

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

View File

@ -239,7 +239,7 @@ class GrowattData:
date_now = dt_util.now().date() date_now = dt_util.now().date()
last_updated_time = dt_util.parse_time(str(sorted_keys[-1])) last_updated_time = dt_util.parse_time(str(sorted_keys[-1]))
mix_detail["lastdataupdate"] = datetime.datetime.combine( 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 # 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, hour,
minute, minute,
second, 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. # Only set up listener if time is now or in the future.
if trigger_dt >= dt_util.now(): 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 the user passed in an initial value with a timezone, convert it to right tz
if current_datetime.tzinfo is not None: if current_datetime.tzinfo is not None:
self._current_datetime = current_datetime.astimezone( self._current_datetime = current_datetime.astimezone(
dt_util.DEFAULT_TIME_ZONE dt_util.get_default_time_zone()
) )
else: else:
self._current_datetime = current_datetime.replace( self._current_datetime = current_datetime.replace(
tzinfo=dt_util.DEFAULT_TIME_ZONE tzinfo=dt_util.get_default_time_zone()
) )
@classmethod @classmethod
@ -295,7 +295,7 @@ class InputDatetime(collection.CollectionEntity, RestoreEntity):
) )
self._current_datetime = current_datetime.replace( self._current_datetime = current_datetime.replace(
tzinfo=dt_util.DEFAULT_TIME_ZONE tzinfo=dt_util.get_default_time_zone()
) )
@property @property
@ -409,7 +409,7 @@ class InputDatetime(collection.CollectionEntity, RestoreEntity):
time = self._current_datetime.time() time = self._current_datetime.time()
self._current_datetime = py_datetime.datetime.combine( 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() self.async_write_ha_state()

View File

@ -80,7 +80,7 @@ class KNXDateTime(KnxEntity, DateTimeEntity, RestoreEntity):
): ):
self._device.remote_value.value = ( self._device.remote_value.value = (
datetime.fromisoformat(last_state.state) datetime.fromisoformat(last_state.state)
.astimezone(dt_util.DEFAULT_TIME_ZONE) .astimezone(dt_util.get_default_time_zone())
.timetuple() .timetuple()
) )
@ -96,9 +96,11 @@ class KNXDateTime(KnxEntity, DateTimeEntity, RestoreEntity):
hour=time_struct.tm_hour, hour=time_struct.tm_hour,
minute=time_struct.tm_min, minute=time_struct.tm_min,
second=min(time_struct.tm_sec, 59), # account for leap seconds 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: async def async_set_value(self, value: datetime) -> None:
"""Change the value.""" """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, entity_category=EntityCategory.CONFIG,
value_fn=lambda robot: _as_local_time(robot.sleep_mode_start_time), value_fn=lambda robot: _as_local_time(robot.sleep_mode_start_time),
set_fn=lambda robot, value: robot.set_sleep_mode( 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.""" """Return diagnostics for a config entry."""
payload: dict[str, Any] = { payload: dict[str, Any] = {
"now": dt_util.now().isoformat(), "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), "system_timezone": str(datetime.datetime.now().astimezone().tzinfo),
} }
store = hass.data[DOMAIN][config_entry.entry_id] store = hass.data[DOMAIN][config_entry.entry_id]

View File

@ -134,7 +134,7 @@ class LocalTodoListEntity(TodoListEntity):
self._attr_unique_id = unique_id self._attr_unique_id = unique_id
def _new_todo_store(self) -> TodoStore: 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: async def async_update(self) -> None:
"""Update entity state based on the local To-do items.""" """Update entity state based on the local To-do items."""

View File

@ -80,7 +80,7 @@ class MetWeatherData:
if not resp: if not resp:
raise CannotConnect raise CannotConnect
self.current_weather_data = self._weather_data.get_current_weather() 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.daily_forecast = self._weather_data.get_forecast(time_zone, False, 0)
self.hourly_forecast = self._weather_data.get_forecast(time_zone, True) self.hourly_forecast = self._weather_data.get_forecast(time_zone, True)
return self return self

View File

@ -86,7 +86,7 @@ class MetEireannWeatherData:
"""Fetch data from API - (current weather and forecast).""" """Fetch data from API - (current weather and forecast)."""
await self._weather_data.fetching_data() await self._weather_data.fetching_data()
self.current_weather_data = self._weather_data.get_current_weather() 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.daily_forecast = self._weather_data.get_forecast(time_zone, False)
self.hourly_forecast = self._weather_data.get_forecast(time_zone, True) self.hourly_forecast = self._weather_data.get_forecast(time_zone, True)
return self return self

View File

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

View File

@ -251,13 +251,13 @@ class ONVIFDevice:
LOGGER.debug("%s: Device time: %s", self.name, device_time) 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 cdate = device_time.LocalDateTime
if device_time.UTCDateTime: if device_time.UTCDateTime:
tzone = dt_util.UTC tzone = dt_util.UTC
cdate = device_time.UTCDateTime cdate = device_time.UTCDateTime
elif device_time.TimeZone: 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: if cdate is None:
LOGGER.warning("%s: Could not retrieve date/time on this camera", self.name) 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 schedule = self.coordinator.data
if not schedule: if not schedule:
return None 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() dt_util.now()
) )
program_event = next(cursor, None) 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 # We have to recreate _local_from_timestamp in the closure in case the timezone changes
_local_from_timestamp = partial( _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: 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 # We have to recreate _local_from_timestamp in the closure in case the timezone changes
_local_from_timestamp = partial( _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: 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 # We have to recreate _local_from_timestamp in the closure in case the timezone changes
_local_from_timestamp = partial( _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: def _same_month_ts(time1: float, time2: float) -> bool:

View File

@ -115,7 +115,7 @@ class RiscoSensor(CoordinatorEntity[RiscoEventsDataUpdateCoordinator], SensorEnt
return None return None
if res := dt_util.parse_datetime(self._event.time): 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 return None
@property @property

View File

@ -10,6 +10,8 @@ from homeassistant.util.dt import get_time_zone
from .const import DOMAIN, LOGGER from .const import DOMAIN, LOGGER
EUROPE_AMSTERDAM_ZONE_INFO = get_time_zone("Europe/Amsterdam")
class RovaCoordinator(DataUpdateCoordinator[dict[str, datetime]]): class RovaCoordinator(DataUpdateCoordinator[dict[str, datetime]]):
"""Class to manage fetching Rova data.""" """Class to manage fetching Rova data."""
@ -33,7 +35,7 @@ class RovaCoordinator(DataUpdateCoordinator[dict[str, datetime]]):
for item in items: for item in items:
date = datetime.strptime(item["Date"], "%Y-%m-%dT%H:%M:%S").replace( 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() code = item["GarbageTypeCode"].lower()
if code not in data: 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 from .const import DOMAIN, LOGGER, MIN_TIME_BETWEEN_UPDATES, PHOENIX_TIME_ZONE
TIMEOUT = 10 TIMEOUT = 10
PHOENIX_ZONE_INFO = dt_util.get_time_zone(PHOENIX_TIME_ZONE)
class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]): class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]):
@ -43,8 +44,7 @@ class SRPEnergyDataUpdateCoordinator(DataUpdateCoordinator[float]):
""" """
LOGGER.debug("async_update_data enter") LOGGER.debug("async_update_data enter")
# Fetch srp_energy data # Fetch srp_energy data
phx_time_zone = dt_util.get_time_zone(PHOENIX_TIME_ZONE) end_date = dt_util.now(PHOENIX_ZONE_INFO)
end_date = dt_util.now(phx_time_zone)
start_date = end_date - timedelta(days=1) start_date = end_date - timedelta(days=1)
try: try:
async with asyncio.timeout(TIMEOUT): 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( tibber_connection = tibber.Tibber(
access_token=entry.data[CONF_ACCESS_TOKEN], access_token=entry.data[CONF_ACCESS_TOKEN],
websession=async_get_clientsession(hass), 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 hass.data[DOMAIN] = tibber_connection

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -109,7 +109,7 @@ class ValloxFilterRemainingSensor(ValloxSensorEntity):
return datetime.combine( return datetime.combine(
next_filter_change_date, 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) _raise_issue_if_no_country(hass, hass.config.country)
if CONF_TIME_ZONE in config: 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 CONF_MEDIA_DIRS not in config:
if is_docker_env(): if is_docker_env():

View File

@ -2951,16 +2951,38 @@ class Config:
"debug": self.debug, "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.""" """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): if time_zone := dt_util.get_time_zone(time_zone_str):
self.time_zone = time_zone_str self.time_zone = time_zone_str
dt_util.set_default_time_zone(time_zone) dt_util.set_default_time_zone(time_zone)
else: else:
raise ValueError(f"Received invalid time zone {time_zone_str}") raise ValueError(f"Received invalid time zone {time_zone_str}")
@callback async def _async_update(
def _update(
self, self,
*, *,
source: ConfigSource, source: ConfigSource,
@ -2993,7 +3015,7 @@ class Config:
if location_name is not None: if location_name is not None:
self.location_name = location_name self.location_name = location_name
if time_zone is not None: 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: if external_url is not _UNDEF:
self.external_url = cast(str | None, external_url) self.external_url = cast(str | None, external_url)
if internal_url is not _UNDEF: if internal_url is not _UNDEF:
@ -3013,7 +3035,7 @@ class Config:
_raise_issue_if_no_country, _raise_issue_if_no_country,
) )
self._update(source=ConfigSource.STORAGE, **kwargs) await self._async_update(source=ConfigSource.STORAGE, **kwargs)
await self._async_store() await self._async_store()
self.hass.bus.async_fire_internal(EVENT_CORE_CONFIG_UPDATE, kwargs) 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") _LOGGER.warning("Invalid internal_url set. It's not allowed to have a path")
self._update( await self._async_update(
source=ConfigSource.STORAGE, source=ConfigSource.STORAGE,
latitude=data.get("latitude"), latitude=data.get("latitude"),
longitude=data.get("longitude"), longitude=data.get("longitude"),

View File

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

View File

@ -5,11 +5,12 @@ from __future__ import annotations
import bisect import bisect
from contextlib import suppress from contextlib import suppress
import datetime as dt import datetime as dt
from functools import partial from functools import lru_cache, partial
import re import re
from typing import Any, Literal, overload from typing import Any, Literal, overload
import zoneinfo import zoneinfo
from aiozoneinfo import async_get_time_zone as _async_get_time_zone
import ciso8601 import ciso8601
DATE_STR_FORMAT = "%Y-%m-%d" 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: def set_default_time_zone(time_zone: dt.tzinfo) -> None:
"""Set a default time zone to be used when none is specified. """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) assert isinstance(time_zone, dt.tzinfo)
DEFAULT_TIME_ZONE = time_zone DEFAULT_TIME_ZONE = time_zone
get_default_time_zone.cache_clear()
def get_time_zone(time_zone_str: str) -> dt.tzinfo | None: def get_time_zone(time_zone_str: str) -> dt.tzinfo | None:
"""Get time zone from string. Return None if unable to determine. """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: try:
return zoneinfo.ZoneInfo(time_zone_str) return zoneinfo.ZoneInfo(time_zone_str)
@ -98,6 +107,17 @@ def get_time_zone(time_zone_str: str) -> dt.tzinfo | None:
return 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 # We use a partial here since it is implemented in native code
# and avoids the global lookup of UTC # and avoids the global lookup of UTC
utcnow = partial(dt.datetime.now, UTC) utcnow = partial(dt.datetime.now, UTC)

View File

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

View File

@ -9,6 +9,7 @@ aiohttp_cors==0.7.0
aiohttp_session==2.12.0 aiohttp_session==2.12.0
aiohttp-fast-url-dispatcher==0.3.0 aiohttp-fast-url-dispatcher==0.3.0
aiohttp-fast-zlib==0.1.0 aiohttp-fast-zlib==0.1.0
aiozoneinfo==0.1.0
astral==2.2 astral==2.2
async-interrupt==1.1.1 async-interrupt==1.1.1
attrs==23.2.0 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_job = hass.async_add_job
orig_async_add_executor_job = hass.async_add_executor_job orig_async_add_executor_job = hass.async_add_executor_job
orig_async_create_task_internal = hass.async_create_task_internal 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): def async_add_job(target, *args, eager_start: bool = False):
"""Add job.""" """Add job."""
@ -279,7 +279,7 @@ async def async_test_home_assistant(
hass.config.latitude = 32.87336 hass.config.latitude = 32.87336
hass.config.longitude = -117.22743 hass.config.longitude = -117.22743
hass.config.elevation = 0 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.units = METRIC_SYSTEM
hass.config.media_dirs = {"local": get_test_config_dir("media")} hass.config.media_dirs = {"local": get_test_config_dir("media")}
hass.config.skip_pip = True hass.config.skip_pip = True
@ -361,7 +361,7 @@ async def async_test_home_assistant(
yield hass yield hass
# Restore timezone, it is set when creating the hass object # 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( def async_mock_service(

View File

@ -71,7 +71,7 @@ async def test_form_options(
) -> None: ) -> None:
"""Test the form options.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
with patch( with patch(
"homeassistant.components.aemet.AEMET.api_call", "homeassistant.components.aemet.AEMET.api_call",
@ -112,7 +112,7 @@ async def test_form_duplicated_id(
) -> None: ) -> None:
"""Test setting up duplicated entry.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
with patch( with patch(
"homeassistant.components.aemet.AEMET.api_call", "homeassistant.components.aemet.AEMET.api_call",

View File

@ -20,7 +20,7 @@ async def test_coordinator_error(
) -> None: ) -> None:
"""Test error on coordinator update.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass) await async_init_integration(hass)

View File

@ -28,7 +28,7 @@ async def test_unload_entry(
) -> None: ) -> None:
"""Test (un)loading the AEMET integration.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
with patch( with patch(
"homeassistant.components.aemet.AEMET.api_call", "homeassistant.components.aemet.AEMET.api_call",
@ -54,7 +54,7 @@ async def test_init_town_not_found(
) -> None: ) -> None:
"""Test TownNotFound when loading the AEMET integration.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
with patch( with patch(
"homeassistant.components.aemet.AEMET.api_call", "homeassistant.components.aemet.AEMET.api_call",
@ -80,7 +80,7 @@ async def test_init_api_timeout(
) -> None: ) -> None:
"""Test API timeouts when loading the AEMET integration.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
with patch( with patch(
"homeassistant.components.aemet.AEMET.api_call", "homeassistant.components.aemet.AEMET.api_call",

View File

@ -15,7 +15,7 @@ async def test_aemet_forecast_create_sensors(
) -> None: ) -> None:
"""Test creation of forecast sensors.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass) await async_init_integration(hass)
@ -76,7 +76,7 @@ async def test_aemet_weather_create_sensors(
) -> None: ) -> None:
"""Test creation of weather sensors.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
await async_init_integration(hass) await async_init_integration(hass)

View File

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

View File

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

View File

@ -91,9 +91,9 @@ def platforms() -> list[Platform]:
@pytest.fixture(autouse=True) @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.""" """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") @pytest.fixture(name="todos")

View File

@ -28,11 +28,11 @@ TEST_DOMAIN = "test"
@pytest.fixture @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 the time zone for the tests."""
# Set our timezone to CST/Regina so we can check calculations # Set our timezone to CST/Regina so we can check calculations
# This keeps UTC-6 all year round # 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): class MockFlow(ConfigFlow):

View File

@ -700,8 +700,8 @@ async def test_event_start_trigger_dst(
freezer: FrozenDateTimeFactory, freezer: FrozenDateTimeFactory,
) -> None: ) -> None:
"""Test a calendar event trigger happening at the start of daylight savings time.""" """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") 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") freezer.move_to("2023-03-12 01:00:00-08:00")
# Before DST transition starts # 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: async def test_datetime(hass: HomeAssistant) -> None:
"""Test date/time entity.""" """Test date/time entity."""
hass.config.set_time_zone("UTC") await hass.config.async_set_time_zone("UTC")
setup_test_component_platform( setup_test_component_platform(
hass, hass,
DOMAIN, DOMAIN,

View File

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

View File

@ -24,7 +24,7 @@ from .conftest import ComponentSetup, YieldFixture
from tests.common import MockConfigEntry 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_TZ_NAME = "Pacific/Auckland"
TEST_TIMEZONE = zoneinfo.ZoneInfo(TEST_TZ_NAME) TEST_TIMEZONE = zoneinfo.ZoneInfo(TEST_TZ_NAME)

View File

@ -28,9 +28,9 @@ from tests.components.light.common import MockLight
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def set_utc(hass): async def set_utc(hass):
"""Set timezone to UTC.""" """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: 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, autospec=True,
) as forecast_solar_mock: ) as forecast_solar_mock:
forecast_solar = forecast_solar_mock.return_value 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 = MagicMock(spec=models.Estimate)
estimate.now.return_value = now estimate.now.return_value = now
@ -79,10 +79,10 @@ def mock_forecast_solar(hass) -> Generator[None, MagicMock, None]:
estimate.energy_production_tomorrow = 200000 estimate.energy_production_tomorrow = 200000
estimate.power_production_now = 300000 estimate.power_production_now = 300000
estimate.power_highest_peak_time_today = datetime( 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( 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 estimate.energy_current_hour = 800000
@ -96,16 +96,16 @@ def mock_forecast_solar(hass) -> Generator[None, MagicMock, None]:
1: 900000, 1: 900000,
}.get }.get
estimate.watts = { estimate.watts = {
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 10, datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 10,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 100, datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 100,
} }
estimate.wh_days = { estimate.wh_days = {
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 20, datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 20,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 200, datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 200,
} }
estimate.wh_period = { estimate.wh_period = {
datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 30, datetime(2021, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 30,
datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE): 300, datetime(2022, 6, 27, 13, 0, tzinfo=dt_util.get_default_time_zone()): 300,
} }
forecast_solar.estimate.return_value = estimate forecast_solar.estimate.return_value = estimate

View File

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

View File

@ -474,7 +474,7 @@ async def test_http_api_event(
component_setup, component_setup,
) -> None: ) -> None:
"""Test querying the API and fetching events from the server.""" """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 = { event = {
**TEST_EVENT, **TEST_EVENT,
**upcoming(), **upcoming(),
@ -788,7 +788,7 @@ async def test_all_day_iter_order(
event_order, event_order,
) -> None: ) -> None:
"""Test the sort order of an all day events depending on the time zone.""" """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( mock_events_list_items(
[ [
{ {

View File

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

View File

@ -241,7 +241,7 @@ async def test_history_during_period_significant_domain(
time_zone, time_zone,
) -> None: ) -> None:
"""Test history_during_period with climate domain.""" """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() now = dt_util.utcnow()
await async_setup_component(hass, "history", {}) 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, hass: HomeAssistant,
) -> None: ) -> None:
"""Test we startup from history and switch to watching state changes.""" """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() utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0) 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, hass: HomeAssistant,
) -> None: ) -> None:
"""Test we startup from history and switch to watching state changes with an expanding end time.""" """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() utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0) 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, hass: HomeAssistant,
) -> None: ) -> None:
"""Test we startup from history and switch to watching state changes.""" """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() utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0) 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 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() utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0) 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: async def test_measure_cet(recorder_mock: Recorder, hass: HomeAssistant) -> None:
"""Test the history statistics sensor measure with a non-UTC timezone.""" """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) start_time = dt_util.utcnow() - timedelta(minutes=60)
t0 = start_time + timedelta(minutes=20) t0 = start_time + timedelta(minutes=20)
t1 = t0 + timedelta(minutes=10) t1 = t0 + timedelta(minutes=10)
@ -1446,7 +1446,7 @@ async def test_end_time_with_microseconds_zeroed(
hass: HomeAssistant, hass: HomeAssistant,
) -> None: ) -> None:
"""Test the history statistics sensor that has the end time microseconds zeroed out.""" """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( start_of_today = dt_util.now().replace(
day=9, month=7, year=1986, hour=0, minute=0, second=0, microsecond=0 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, hass: HomeAssistant,
) -> None: ) -> None:
"""Test we account for microseconds when doing the data calculation.""" """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() utcnow = dt_util.utcnow()
start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0) start_time = utcnow.replace(hour=0, minute=0, second=0, microsecond=0)
last_times = None 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: async def test_timestamp(hass: HomeAssistant) -> None:
"""Test timestamp.""" """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( assert await async_setup_component(
hass, hass,

View File

@ -21,9 +21,9 @@ from tests.common import MockConfigEntry, async_fire_time_changed
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def set_utc(hass: HomeAssistant) -> None: async def set_utc(hass: HomeAssistant) -> None:
"""Set timezone to UTC.""" """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: async def test_successful_config_entry(hass: HomeAssistant) -> None:

View File

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

View File

@ -184,7 +184,7 @@ async def test_issur_melacha_sensor(
time_zone = dt_util.get_time_zone(tzname) time_zone = dt_util.get_time_zone(tzname)
test_time = now.replace(tzinfo=time_zone) 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.latitude = latitude
hass.config.longitude = longitude hass.config.longitude = longitude
@ -272,7 +272,7 @@ async def test_issur_melacha_sensor_update(
time_zone = dt_util.get_time_zone(tzname) time_zone = dt_util.get_time_zone(tzname)
test_time = now.replace(tzinfo=time_zone) 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.latitude = latitude
hass.config.longitude = longitude hass.config.longitude = longitude

View File

@ -167,7 +167,7 @@ async def test_jewish_calendar_sensor(
time_zone = dt_util.get_time_zone(tzname) time_zone = dt_util.get_time_zone(tzname)
test_time = now.replace(tzinfo=time_zone) 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.latitude = latitude
hass.config.longitude = longitude hass.config.longitude = longitude
@ -512,7 +512,7 @@ async def test_shabbat_times_sensor(
time_zone = dt_util.get_time_zone(tzname) time_zone = dt_util.get_time_zone(tzname)
test_time = now.replace(tzinfo=time_zone) 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.latitude = latitude
hass.config.longitude = longitude 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: async def test_date_restore_and_respond(hass: HomeAssistant, knx: KNXTestKit) -> None:
"""Test KNX datetime with passive_address, restoring state and respond_to_read.""" """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_address = "1/1/1"
test_passive_address = "3/3/3" test_passive_address = "3/3/3"
fake_state = State("datetime.test", "2022-03-03T03:04:05+00:00") fake_state = State("datetime.test", "2022-03-03T03:04:05+00:00")

View File

@ -33,7 +33,7 @@ async def test_calendar_events(
) -> None: ) -> None:
"""Test the calendar.""" """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) freezer.move_to(test_time)
await async_init_integration(hass, mock_config_entry) await async_init_integration(hass, mock_config_entry)
@ -86,8 +86,8 @@ async def test_calendar_edge_cases(
end_date: datetime, end_date: datetime,
) -> None: ) -> None:
"""Test edge cases.""" """Test edge cases."""
start_date = start_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.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 # set schedule to be only on Sunday, 07:00 - 07:30
mock_lamarzocco.schedule[2]["enable"] = "Disabled" 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.""" """Assert no events when global auto on/off is disabled."""
mock_lamarzocco.current_status["global_auto"] = "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) freezer.move_to(test_time)
await async_init_integration(hass, mock_config_entry) await async_init_integration(hass, mock_config_entry)

View File

@ -87,11 +87,11 @@ def mock_time_zone() -> str:
@pytest.fixture(autouse=True) @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 the time zone for the tests."""
# Set our timezone to CST/Regina so we can check calculations # Set our timezone to CST/Regina so we can check calculations
# This keeps UTC-6 all year round # 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") @pytest.fixture(name="config_entry")

View File

@ -61,9 +61,9 @@ async def ws_move_item(
@pytest.fixture(autouse=True) @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.""" """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 = { EXPECTED_ADD_ITEM = {

View File

@ -68,9 +68,9 @@ async def hass_(recorder_mock, hass):
@pytest.fixture @pytest.fixture
def set_utc(hass): async def set_utc(hass):
"""Set timezone to UTC.""" """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: async def test_service_call_create_logbook_entry(hass_) -> None:

View File

@ -47,9 +47,9 @@ from tests.typing import RecorderInstanceGenerator, WebSocketGenerator
@pytest.fixture @pytest.fixture
def set_utc(hass): async def set_utc(hass):
"""Set timezone to UTC.""" """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]: def listeners_without_writes(listeners: dict[str, int]) -> dict[str, int]:

View File

@ -39,7 +39,7 @@ async def test_sensor(
freezer: FrozenDateTimeFactory, freezer: FrozenDateTimeFactory,
) -> None: ) -> None:
"""Test states of the air_quality.""" """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") freezer.move_to("2024-04-20 12:00:00+00:00")
with patch("homeassistant.components.nam.PLATFORMS", [Platform.SENSOR]): 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 - Configure options to introduce API Token, with bad auth and good one
""" """
freezer.move_to(_MOCK_TIME_VALID_RESPONSES) 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 = { tst_config = {
CONF_NAME: "test", CONF_NAME: "test",
ATTR_TARIFF: TARIFFS[1], ATTR_TARIFF: TARIFFS[1],
@ -184,7 +184,7 @@ async def test_reauth(
) -> None: ) -> None:
"""Test reauth flow for API-token mode.""" """Test reauth flow for API-token mode."""
freezer.move_to(_MOCK_TIME_BAD_AUTH_RESPONSES) 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 = { tst_config = {
CONF_NAME: "test", CONF_NAME: "test",
ATTR_TARIFF: TARIFFS[1], ATTR_TARIFF: TARIFFS[1],

View File

@ -91,9 +91,9 @@ async def setup_config_entry(
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def set_time_zone(hass: HomeAssistant): async def set_time_zone(hass: HomeAssistant):
"""Set the time zone for the tests.""" """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) @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 includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned). 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) zero, four, states = record_states(hass)
await async_wait_recording_done(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 includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned). 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) zero, four, states = record_states(hass)
await async_wait_recording_done(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 includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned). 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) zero, four, states = record_states(hass)
await async_wait_recording_done(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: async def test_auto_purge(hass: HomeAssistant, setup_recorder: None) -> None:
"""Test periodic purge scheduling.""" """Test periodic purge scheduling."""
timezone = "Europe/Copenhagen" timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone) await hass.config.async_set_time_zone(timezone)
tz = dt_util.get_time_zone(timezone) tz = dt_util.get_time_zone(timezone)
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by # 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: ) -> None:
"""Test periodic purge scheduling does a repack on the 2nd sunday.""" """Test periodic purge scheduling does a repack on the 2nd sunday."""
timezone = "Europe/Copenhagen" timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone) await hass.config.async_set_time_zone(timezone)
tz = dt_util.get_time_zone(timezone) tz = dt_util.get_time_zone(timezone)
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by # 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: ) -> None:
"""Test periodic purge scheduling does not auto repack on the 2nd sunday if disabled.""" """Test periodic purge scheduling does not auto repack on the 2nd sunday if disabled."""
timezone = "Europe/Copenhagen" 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}) await async_setup_recorder_instance(hass, {CONF_AUTO_REPACK: False})
tz = dt_util.get_time_zone(timezone) tz = dt_util.get_time_zone(timezone)
@ -1176,7 +1176,7 @@ async def test_auto_purge_no_auto_repack_on_not_second_sunday(
) -> None: ) -> None:
"""Test periodic purge scheduling does not do a repack unless its the 2nd sunday.""" """Test periodic purge scheduling does not do a repack unless its the 2nd sunday."""
timezone = "Europe/Copenhagen" timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone) await hass.config.async_set_time_zone(timezone)
tz = dt_util.get_time_zone(timezone) tz = dt_util.get_time_zone(timezone)
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by # 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: ) -> None:
"""Test periodic db cleanup still run when auto purge is disabled.""" """Test periodic db cleanup still run when auto purge is disabled."""
timezone = "Europe/Copenhagen" 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}) await async_setup_recorder_instance(hass, {CONF_AUTO_PURGE: False})
tz = dt_util.get_time_zone(timezone) tz = dt_util.get_time_zone(timezone)
@ -1262,7 +1262,7 @@ async def test_auto_statistics(
) -> None: ) -> None:
"""Test periodic statistics scheduling.""" """Test periodic statistics scheduling."""
timezone = "Europe/Copenhagen" timezone = "Europe/Copenhagen"
hass.config.set_time_zone(timezone) await hass.config.async_set_time_zone(timezone)
tz = dt_util.get_time_zone(timezone) tz = dt_util.get_time_zone(timezone)
stats_5min = [] stats_5min = []

View File

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

View File

@ -1102,7 +1102,7 @@ async def test_daily_statistics_sum(
timezone, timezone,
) -> None: ) -> None:
"""Test daily statistics.""" """Test daily statistics."""
hass.config.set_time_zone(timezone) await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass) await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text assert "Statistics already compiled" not in caplog.text
@ -1282,7 +1282,7 @@ async def test_weekly_statistics_mean(
timezone, timezone,
) -> None: ) -> None:
"""Test weekly statistics.""" """Test weekly statistics."""
hass.config.set_time_zone(timezone) await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass) await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text assert "Statistics already compiled" not in caplog.text
@ -1417,7 +1417,7 @@ async def test_weekly_statistics_sum(
timezone, timezone,
) -> None: ) -> None:
"""Test weekly statistics.""" """Test weekly statistics."""
hass.config.set_time_zone(timezone) await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass) await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text assert "Statistics already compiled" not in caplog.text
@ -1597,7 +1597,7 @@ async def test_monthly_statistics_sum(
timezone, timezone,
) -> None: ) -> None:
"""Test monthly statistics.""" """Test monthly statistics."""
hass.config.set_time_zone(timezone) await hass.config.async_set_time_zone(timezone)
await async_wait_recording_done(hass) await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" not in caplog.text assert "Statistics already compiled" not in caplog.text
@ -1917,7 +1917,7 @@ async def test_change(
timezone, timezone,
) -> None: ) -> None:
"""Test deriving change from sum statistic.""" """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) await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" 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 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. 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) await async_wait_recording_done(hass)
assert "Compiling statistics for" not in caplog.text assert "Compiling statistics for" not in caplog.text
assert "Statistics already compiled" 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 recorder_mock: Recorder, hass: HomeAssistant, hass_ws_client: WebSocketGenerator
) -> None: ) -> None:
"""Test statistics_during_period in the past.""" """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() now = dt_util.utcnow().replace()
hass.config.units = US_CUSTOMARY_SYSTEM hass.config.units = US_CUSTOMARY_SYSTEM

View File

@ -32,7 +32,7 @@ async def test_control_event(
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test event update updates correct event object.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
await setup_rfx_test_cfg( await setup_rfx_test_cfg(
@ -60,7 +60,7 @@ async def test_status_event(
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test event update updates correct event object.""" """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") freezer.move_to("2021-01-09 12:00:00+00:00")
await setup_rfx_test_cfg( await setup_rfx_test_cfg(

View File

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

View File

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

View File

@ -20,11 +20,11 @@ from tests.common import MockConfigEntry
@pytest.fixture(name="setup_hass_config", autouse=True) @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.""" """Set up things to be run when tests are started."""
hass.config.latitude = 33.27 hass.config.latitude = 33.27
hass.config.longitude = 112 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") @pytest.fixture(name="hass_tz_info")

View File

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

View File

@ -22,11 +22,11 @@ def hass_time_zone():
@pytest.fixture(autouse=True) @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.""" """Set up things to be run when tests are started."""
hass.config.latitude = 50.27583 hass.config.latitude = 50.27583
hass.config.longitude = 18.98583 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 @pytest.fixture

View File

@ -113,9 +113,9 @@ def mock_setup_integration(hass: HomeAssistant) -> None:
@pytest.fixture(autouse=True) @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.""" """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( async def create_mock_platform(

View File

@ -42,9 +42,9 @@ def platforms() -> list[Platform]:
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def set_time_zone(hass: HomeAssistant): async def set_time_zone(hass: HomeAssistant):
"""Set the time zone for the tests.""" """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: 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) @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.""" """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( @pytest.mark.parametrize(

View File

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

View File

@ -18,21 +18,21 @@ def set_tz(request):
@pytest.fixture @pytest.fixture
def utc(hass: HomeAssistant) -> None: async def utc(hass: HomeAssistant) -> None:
"""Set the default TZ to UTC.""" """Set the default TZ to UTC."""
hass.config.set_time_zone("UTC") hass.config.async_set_time_zone("UTC")
@pytest.fixture @pytest.fixture
def helsinki(hass: HomeAssistant) -> None: async def helsinki(hass: HomeAssistant) -> None:
"""Set the default TZ to Europe/Helsinki.""" """Set the default TZ to Europe/Helsinki."""
hass.config.set_time_zone("Europe/Helsinki") hass.config.async_set_time_zone("Europe/Helsinki")
@pytest.fixture @pytest.fixture
def new_york(hass: HomeAssistant) -> None: async def new_york(hass: HomeAssistant) -> None:
"""Set the default TZ to America/New_York.""" """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): 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 hass: HomeAssistant, now: datetime, sign: str, element: str, modality: str
) -> None: ) -> None:
"""Test the zodiac sensor.""" """Test the zodiac sensor."""
hass.config.set_time_zone("UTC") await hass.config.async_set_time_zone("UTC")
MockConfigEntry( MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
).add_to_hass(hass) ).add_to_hass(hass)

View File

@ -1455,7 +1455,9 @@ def hass_recorder(
) -> HomeAssistant: ) -> HomeAssistant:
"""Set up with params.""" """Set up with params."""
if timezone is not None: 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) init_recorder_component(hass, config, recorder_db_url)
hass.start() hass.start()
hass.block_till_done() 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 at 7 AM and sunset at 3AM during summer
After sunrise is true from sunrise until midnight, local time. 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.latitude = 66.5
hass.config.longitude = 162.4 hass.config.longitude = 162.4
await async_setup_component( 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 at 7 AM and sunset at 3AM during summer
Before sunrise is true from midnight until sunrise, local time. 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.latitude = 66.5
hass.config.longitude = 162.4 hass.config.longitude = 162.4
await async_setup_component( 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 at 7 AM and sunset at 3AM during summer
Before sunset is true from midnight until sunset, local time. 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.latitude = 66.5
hass.config.longitude = 162.4 hass.config.longitude = 162.4
await async_setup_component( 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 at 7 AM and sunset at 3AM during summer
After sunset is true from sunset until midnight, local time. 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.latitude = 66.5
hass.config.longitude = 162.4 hass.config.longitude = 162.4
await async_setup_component( 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 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: 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 hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None: ) -> None:
"""Test periodic task behavior when entering dst.""" """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 = [] specific_runs = []
today = date.today().isoformat() 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) 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 = [] specific_runs = []
today = date.today().isoformat() today = date.today().isoformat()
@ -4198,7 +4198,7 @@ async def test_periodic_task_leaving_dst(
hass: HomeAssistant, freezer: FrozenDateTimeFactory hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None: ) -> None:
"""Test periodic task behavior when leaving dst.""" """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 = [] specific_runs = []
today = date.today().isoformat() today = date.today().isoformat()
@ -4274,7 +4274,7 @@ async def test_periodic_task_leaving_dst_2(
hass: HomeAssistant, freezer: FrozenDateTimeFactory hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None: ) -> None:
"""Test periodic task behavior when leaving dst.""" """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 = [] specific_runs = []
today = date.today().isoformat() 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.""" """Test cancel of async track point in time."""
times = [] 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") hst_tz = dt_util.get_time_zone("US/Hawaii")
@ha.callback @ha.callback

View File

@ -1108,9 +1108,9 @@ def test_strptime(hass: HomeAssistant) -> None:
assert render(hass, "{{ strptime('invalid', '%Y', default=1) }}") == 1 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.""" """Test the timestamps to custom filter."""
hass.config.set_time_zone("UTC") await hass.config.async_set_time_zone("UTC")
now = dt_util.utcnow() now = dt_util.utcnow()
tests = [ tests = [
(1469119144, None, True, "2016-07-21 16:39:04"), (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 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.""" """Test the timestamps to local filter."""
hass.config.set_time_zone("UTC") await hass.config.async_set_time_zone("UTC")
tests = [ tests = [
(1469119144, "2016-07-21T16:39:04+00:00"), (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", "homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True, return_value=True,
) )
def test_today_at( async def test_today_at(
mock_is_safe, hass: HomeAssistant, now, expected, expected_midnight, timezone_str mock_is_safe, hass: HomeAssistant, now, expected, expected_midnight, timezone_str
) -> None: ) -> None:
"""Test today_at method.""" """Test today_at method."""
freezer = freeze_time(now) freezer = freeze_time(now)
freezer.start() freezer.start()
hass.config.set_time_zone(timezone_str) await hass.config.async_set_time_zone(timezone_str)
result = template.Template( result = template.Template(
"{{ today_at('10:00').isoformat() }}", "{{ today_at('10:00').isoformat() }}",
@ -2273,9 +2273,9 @@ def test_today_at(
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable", "homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True, 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.""" """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") now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
relative_time_template = ( relative_time_template = (
'{{relative_time(strptime("2000-01-01 09:00:00", "%Y-%m-%d %H:%M:%S"))}}' '{{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", "homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True, 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.""" """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") now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
time_since_template = ( time_since_template = (
'{{time_since(strptime("2000-01-01 09:00:00", "%Y-%m-%d %H:%M:%S"))}}' '{{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", "homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True, 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.""" """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") now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
time_until_template = ( time_until_template = (
'{{time_until(strptime("2000-01-01 11:00:00", "%Y-%m-%d %H:%M:%S"))}}' '{{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") 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 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" 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 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: def test_get_time_zone_returns_none_for_garbage_time_zone() -> None:
"""Test getting a non existing time zone.""" """Test getting a non existing time zone."""
assert dt_util.get_time_zone("Non existing time zone") is None 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: def test_set_default_time_zone() -> None:
"""Test setting default time zone.""" """Test setting default time zone."""
time_zone = dt_util.get_time_zone(TEST_TIME_ZONE) time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)