Migrate from pytz to python-dateutil (#49643)

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
J. Nick Koston 2021-05-08 00:46:26 -05:00 committed by GitHub
parent 13fe837fd2
commit bf2d40adfe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 325 additions and 361 deletions

View file

@ -95,8 +95,14 @@ async def async_attach_trigger(hass, config, action, automation_info):
if has_date:
# If input_datetime has date, then track point in time.
trigger_dt = dt_util.DEFAULT_TIME_ZONE.localize(
datetime(year, month, day, hour, minute, second)
trigger_dt = datetime(
year,
month,
day,
hour,
minute,
second,
tzinfo=dt_util.DEFAULT_TIME_ZONE,
)
# Only set up listener if time is now or in the future.
if trigger_dt >= dt_util.now():

View file

@ -4,13 +4,12 @@ import logging
from aiohttp import ClientConnectorError
from pygti.exceptions import InvalidAuth
from pytz import timezone
from homeassistant.components.sensor import SensorEntity
from homeassistant.const import ATTR_ATTRIBUTION, ATTR_ID, DEVICE_CLASS_TIMESTAMP
from homeassistant.helpers import aiohttp_client
from homeassistant.util import Throttle
from homeassistant.util.dt import utcnow
from homeassistant.util.dt import get_time_zone, utcnow
from .const import ATTRIBUTION, CONF_STATION, DOMAIN, MANUFACTURER
@ -28,6 +27,7 @@ ATTR_DELAY = "delay"
ATTR_NEXT = "next"
PARALLEL_UPDATES = 0
BERLIN_TIME_ZONE = get_time_zone("Europe/Berlin")
_LOGGER = logging.getLogger(__name__)
@ -60,12 +60,11 @@ class HVVDepartureSensor(SensorEntity):
@Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self, **kwargs):
"""Update the sensor."""
departure_time = utcnow() + timedelta(
minutes=self.config_entry.options.get("offset", 0)
)
departure_time_tz_berlin = departure_time.astimezone(timezone("Europe/Berlin"))
departure_time_tz_berlin = departure_time.astimezone(BERLIN_TIME_ZONE)
payload = {
"station": self.config_entry.data[CONF_STATION],

View file

@ -224,8 +224,8 @@ class InputDatetime(RestoreEntity):
dt_util.DEFAULT_TIME_ZONE
)
else:
self._current_datetime = dt_util.DEFAULT_TIME_ZONE.localize(
current_datetime
self._current_datetime = current_datetime.replace(
tzinfo=dt_util.DEFAULT_TIME_ZONE
)
@classmethod
@ -388,8 +388,8 @@ class InputDatetime(RestoreEntity):
if not time:
time = self._current_datetime.time()
self._current_datetime = dt_util.DEFAULT_TIME_ZONE.localize(
py_datetime.datetime.combine(date, time)
self._current_datetime = py_datetime.datetime.combine(
date, time, dt_util.DEFAULT_TIME_ZONE
)
self.async_write_ha_state()

View file

@ -3,7 +3,6 @@ from datetime import datetime, timedelta
import logging
import time
from pytz import timezone
import requests
import voluptuous as vol
@ -26,6 +25,7 @@ from homeassistant.const import (
HTTP_OK,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.util import dt as dt_util
_LOGGER = logging.getLogger(__name__)
@ -112,7 +112,6 @@ class RadarrSensor(SensorEntity):
self.ssl = "https" if conf.get(CONF_SSL) else "http"
self._state = None
self.data = []
self._tz = timezone(str(hass.config.time_zone))
self.type = sensor_type
self._name = SENSOR_TYPES[self.type][0]
if self.type == "diskspace":
@ -177,8 +176,9 @@ class RadarrSensor(SensorEntity):
def update(self):
"""Update the data for the sensor."""
start = get_date(self._tz)
end = get_date(self._tz, self.days)
time_zone = dt_util.get_time_zone(self.hass.config.time_zone)
start = get_date(time_zone)
end = get_date(time_zone, self.days)
try:
res = requests.get(
ENDPOINTS[self.type].format(

View file

@ -1,8 +1,8 @@
"""Support for representing current time of the day as binary sensors."""
from datetime import datetime, timedelta
import logging
from typing import Callable
import pytz
import voluptuous as vol
from homeassistant.components.binary_sensor import PLATFORM_SCHEMA, BinarySensorEntity
@ -70,6 +70,7 @@ class TodSensor(BinarySensorEntity):
self._before_offset = before_offset
self._before = before
self._after = after
self._unsub_update: Callable[[], None] = None
@property
def should_poll(self):
@ -81,59 +82,37 @@ class TodSensor(BinarySensorEntity):
"""Return the name of the sensor."""
return self._name
@property
def after(self):
"""Return the timestamp for the beginning of the period."""
return self._time_after
@property
def before(self):
"""Return the timestamp for the end of the period."""
return self._time_before
@property
def is_on(self):
"""Return True is sensor is on."""
if self.after < self.before:
return self.after <= self.current_datetime < self.before
if self._time_after < self._time_before:
return self._time_after <= dt_util.utcnow() < self._time_before
return False
@property
def current_datetime(self):
"""Return local current datetime according to hass configuration."""
return dt_util.utcnow()
@property
def next_update(self):
"""Return the next update point in the UTC time."""
return self._next_update
@property
def extra_state_attributes(self):
"""Return the state attributes of the sensor."""
time_zone = dt_util.get_time_zone(self.hass.config.time_zone)
return {
ATTR_AFTER: self.after.astimezone(self.hass.config.time_zone).isoformat(),
ATTR_BEFORE: self.before.astimezone(self.hass.config.time_zone).isoformat(),
ATTR_NEXT_UPDATE: self.next_update.astimezone(
self.hass.config.time_zone
).isoformat(),
ATTR_AFTER: self._time_after.astimezone(time_zone).isoformat(),
ATTR_BEFORE: self._time_before.astimezone(time_zone).isoformat(),
ATTR_NEXT_UPDATE: self._next_update.astimezone(time_zone).isoformat(),
}
def _naive_time_to_utc_datetime(self, naive_time):
"""Convert naive time from config to utc_datetime with current day."""
# get the current local date from utc time
current_local_date = self.current_datetime.astimezone(
self.hass.config.time_zone
).date()
# calculate utc datetime corecponding to local time
utc_datetime = self.hass.config.time_zone.localize(
datetime.combine(current_local_date, naive_time)
).astimezone(tz=pytz.UTC)
return utc_datetime
current_local_date = (
dt_util.utcnow()
.astimezone(dt_util.get_time_zone(self.hass.config.time_zone))
.date()
)
# calculate utc datetime corresponding to local time
return dt_util.as_utc(datetime.combine(current_local_date, naive_time))
def _calculate_initial_boudary_time(self):
def _calculate_boudary_time(self):
"""Calculate internal absolute time boundaries."""
nowutc = self.current_datetime
nowutc = dt_util.utcnow()
# If after value is a sun event instead of absolute time
if is_sun_event(self._after):
# Calculate the today's event utc time or
@ -177,43 +156,34 @@ class TodSensor(BinarySensorEntity):
self._time_after += self._after_offset
self._time_before += self._before_offset
def _turn_to_next_day(self):
"""Turn to to the next day."""
if is_sun_event(self._after):
self._time_after = get_astral_event_next(
self.hass, self._after, self._time_after - self._after_offset
)
self._time_after += self._after_offset
else:
# Offset is already there
self._time_after += timedelta(days=1)
if is_sun_event(self._before):
self._time_before = get_astral_event_next(
self.hass, self._before, self._time_before - self._before_offset
)
self._time_before += self._before_offset
else:
# Offset is already there
self._time_before += timedelta(days=1)
async def async_added_to_hass(self):
"""Call when entity about to be added to Home Assistant."""
self._calculate_initial_boudary_time()
self._calculate_boudary_time()
self._calculate_next_update()
self._point_in_time_listener(dt_util.now())
@callback
def _clean_up_listener():
if self._unsub_update is not None:
self._unsub_update()
self._unsub_update = None
self.async_on_remove(_clean_up_listener)
self._unsub_update = event.async_track_point_in_utc_time(
self.hass, self._point_in_time_listener, self._next_update
)
def _calculate_next_update(self):
"""Datetime when the next update to the state."""
now = self.current_datetime
if now < self.after:
self._next_update = self.after
now = dt_util.utcnow()
if now < self._time_after:
self._next_update = self._time_after
return
if now < self.before:
self._next_update = self.before
if now < self._time_before:
self._next_update = self._time_before
return
self._turn_to_next_day()
self._next_update = self.after
self._calculate_boudary_time()
self._next_update = self._time_after
@callback
def _point_in_time_listener(self, now):
@ -221,6 +191,6 @@ class TodSensor(BinarySensorEntity):
self._calculate_next_update()
self.async_write_ha_state()
event.async_track_point_in_utc_time(
self.hass, self._point_in_time_listener, self.next_update
self._unsub_update = event.async_track_point_in_utc_time(
self.hass, self._point_in_time_listener, self._next_update
)

View file

@ -7,7 +7,6 @@ import logging
import os
from aiohttp.hdrs import USER_AGENT
import pytz
import requests
import voluptuous as vol
@ -28,7 +27,7 @@ from homeassistant.const import (
__version__,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle
from homeassistant.util import Throttle, dt as dt_util
_LOGGER = logging.getLogger(__name__)
@ -41,6 +40,7 @@ CONF_STATION_ID = "station_id"
DEFAULT_NAME = "zamg"
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10)
VIENNA_TIME_ZONE = dt_util.get_time_zone("Europe/Vienna")
SENSOR_TYPES = {
"pressure": ("Pressure", PRESSURE_HPA, "LDstat hPa", float),
@ -187,7 +187,7 @@ class ZamgData:
date, time = self.data.get("update_date"), self.data.get("update_time")
if date is not None and time is not None:
return datetime.strptime(date + time, "%d-%m-%Y%H:%M").replace(
tzinfo=pytz.timezone("Europe/Vienna")
tzinfo=VIENNA_TIME_ZONE
)
@classmethod
@ -208,7 +208,7 @@ class ZamgData:
"""Get the latest data from ZAMG."""
if self.last_update and (
self.last_update + timedelta(hours=1)
> datetime.utcnow().replace(tzinfo=pytz.utc)
> datetime.utcnow().replace(tzinfo=dt_util.UTC)
):
return # Not time to update yet; data is only hourly

View file

@ -1531,7 +1531,7 @@ class Config:
self.longitude: float = 0
self.elevation: int = 0
self.location_name: str = "Home"
self.time_zone: datetime.tzinfo = dt_util.UTC
self.time_zone: str = "UTC"
self.units: UnitSystem = METRIC_SYSTEM
self.internal_url: str | None = None
self.external_url: str | None = None
@ -1621,17 +1621,13 @@ class Config:
Async friendly.
"""
time_zone = dt_util.UTC.zone
if self.time_zone and getattr(self.time_zone, "zone"):
time_zone = getattr(self.time_zone, "zone")
return {
"latitude": self.latitude,
"longitude": self.longitude,
"elevation": self.elevation,
"unit_system": self.units.as_dict(),
"location_name": self.location_name,
"time_zone": time_zone,
"time_zone": self.time_zone,
"components": self.components,
"config_dir": self.config_dir,
# legacy, backwards compat
@ -1651,7 +1647,7 @@ class Config:
time_zone = dt_util.get_time_zone(time_zone_str)
if time_zone:
self.time_zone = time_zone
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}")
@ -1721,17 +1717,13 @@ class Config:
async def async_store(self) -> None:
"""Store [homeassistant] core config."""
time_zone = dt_util.UTC.zone
if self.time_zone and getattr(self.time_zone, "zone"):
time_zone = getattr(self.time_zone, "zone")
data = {
"latitude": self.latitude,
"longitude": self.longitude,
"elevation": self.elevation,
"unit_system": self.units.name,
"location_name": self.location_name,
"time_zone": time_zone,
"time_zone": self.time_zone,
"external_url": self.external_url,
"internal_url": self.internal_url,
}

View file

@ -24,8 +24,8 @@ paho-mqtt==1.5.1
pillow==8.1.2
pip>=8.0.3,<20.3
pyroute2==0.5.18
python-dateutil==2.8.1
python-slugify==4.0.1
pytz>=2021.1
pyyaml==5.4.1
requests==2.25.1
ruamel.yaml==0.15.100

View file

@ -4,20 +4,16 @@ from __future__ import annotations
from contextlib import suppress
import datetime as dt
import re
from typing import Any, cast
from typing import Any
import ciso8601
import pytz
import pytz.exceptions as pytzexceptions
import pytz.tzinfo as pytzinfo
from dateutil import tz
from homeassistant.const import MATCH_ALL
DATE_STR_FORMAT = "%Y-%m-%d"
NATIVE_UTC = dt.timezone.utc
UTC = pytz.utc
DEFAULT_TIME_ZONE: dt.tzinfo = pytz.utc
UTC = dt.timezone.utc
DEFAULT_TIME_ZONE: dt.tzinfo = dt.timezone.utc
# Copyright (c) Django Software Foundation and individual contributors.
# All rights reserved.
@ -37,7 +33,6 @@ def set_default_time_zone(time_zone: dt.tzinfo) -> None:
"""
global DEFAULT_TIME_ZONE # pylint: disable=global-statement
# NOTE: Remove in the future in favour of typing
assert isinstance(time_zone, dt.tzinfo)
DEFAULT_TIME_ZONE = time_zone
@ -48,15 +43,12 @@ def get_time_zone(time_zone_str: str) -> dt.tzinfo | None:
Async friendly.
"""
try:
return pytz.timezone(time_zone_str)
except pytzexceptions.UnknownTimeZoneError:
return None
return tz.gettz(time_zone_str)
def utcnow() -> dt.datetime:
"""Get now in UTC time."""
return dt.datetime.now(NATIVE_UTC)
return dt.datetime.now(UTC)
def now(time_zone: dt.tzinfo | None = None) -> dt.datetime:
@ -72,7 +64,7 @@ def as_utc(dattim: dt.datetime) -> dt.datetime:
if dattim.tzinfo == UTC:
return dattim
if dattim.tzinfo is None:
dattim = DEFAULT_TIME_ZONE.localize(dattim) # type: ignore
dattim = dattim.replace(tzinfo=DEFAULT_TIME_ZONE)
return dattim.astimezone(UTC)
@ -93,14 +85,14 @@ def as_local(dattim: dt.datetime) -> dt.datetime:
if dattim.tzinfo == DEFAULT_TIME_ZONE:
return dattim
if dattim.tzinfo is None:
dattim = UTC.localize(dattim)
dattim = dattim.replace(tzinfo=DEFAULT_TIME_ZONE)
return dattim.astimezone(DEFAULT_TIME_ZONE)
def utc_from_timestamp(timestamp: float) -> dt.datetime:
"""Return a UTC time from a timestamp."""
return UTC.localize(dt.datetime.utcfromtimestamp(timestamp))
return dt.datetime.utcfromtimestamp(timestamp).replace(tzinfo=UTC)
def start_of_local_day(dt_or_d: dt.date | dt.datetime | None = None) -> dt.datetime:
@ -112,9 +104,7 @@ def start_of_local_day(dt_or_d: dt.date | dt.datetime | None = None) -> dt.datet
else:
date = dt_or_d
return DEFAULT_TIME_ZONE.localize( # type: ignore
dt.datetime.combine(date, dt.time())
)
return dt.datetime.combine(date, dt.time(), tzinfo=DEFAULT_TIME_ZONE)
# Copyright (c) Django Software Foundation and individual contributors.
@ -239,6 +229,12 @@ def parse_time_expression(parameter: Any, min_value: int, max_value: int) -> lis
return res
def _dst_offset_diff(dattim: dt.datetime) -> dt.timedelta:
"""Return the offset when crossing the DST barrier."""
delta = dt.timedelta(hours=24)
return (dattim + delta).utcoffset() - (dattim - delta).utcoffset() # type: ignore[operator]
def find_next_time_expression_time(
now: dt.datetime, # pylint: disable=redefined-outer-name
seconds: list[int],
@ -312,38 +308,28 @@ def find_next_time_expression_time(
result = result.replace(hour=next_hour)
if result.tzinfo is None:
if result.tzinfo in (None, UTC):
return result
# Now we need to handle timezones. We will make this datetime object
# "naive" first and then re-convert it to the target timezone.
# This is so that we can call pytz's localize and handle DST changes.
tzinfo: pytzinfo.DstTzInfo = UTC if result.tzinfo == NATIVE_UTC else result.tzinfo
result = result.replace(tzinfo=None)
try:
result = tzinfo.localize(result, is_dst=None)
except pytzexceptions.AmbiguousTimeError:
if tz.datetime_ambiguous(result):
# This happens when we're leaving daylight saving time and local
# clocks are rolled back. In this case, we want to trigger
# on both the DST and non-DST time. So when "now" is in the DST
# use the DST-on time, and if not, use the DST-off time.
use_dst = bool(now.dst())
result = tzinfo.localize(result, is_dst=use_dst)
except pytzexceptions.NonExistentTimeError:
fold = 1 if now.dst() else 0
if result.fold != fold:
result = result.replace(fold=fold)
if not tz.datetime_exists(result):
# This happens when we're entering daylight saving time and local
# clocks are rolled forward, thus there are local times that do
# not exist. In this case, we want to trigger on the next time
# that *does* exist.
# In the worst case, this will run through all the seconds in the
# time shift, but that's max 3600 operations for once per year
result = result.replace(tzinfo=tzinfo) + dt.timedelta(seconds=1)
return find_next_time_expression_time(result, seconds, minutes, hours)
result_dst = cast(dt.timedelta, result.dst())
now_dst = cast(dt.timedelta, now.dst()) or dt.timedelta(0)
if result_dst >= now_dst:
return result
return find_next_time_expression_time(
result + dt.timedelta(seconds=1), seconds, minutes, hours
)
# Another edge-case when leaving DST:
# When now is in DST and ambiguous *and* the next trigger time we *should*
@ -351,23 +337,11 @@ def find_next_time_expression_time(
# For example: if triggering on 2:30 and now is 28.10.2018 2:30 (in DST)
# we should trigger next on 28.10.2018 2:30 (out of DST), but our
# algorithm above would produce 29.10.2018 2:30 (out of DST)
if tz.datetime_ambiguous(now):
check_result = find_next_time_expression_time(
now + _dst_offset_diff(now), seconds, minutes, hours
)
if tz.datetime_ambiguous(check_result):
return check_result
# Step 1: Check if now is ambiguous
try:
tzinfo.localize(now.replace(tzinfo=None), is_dst=None)
return result
except pytzexceptions.AmbiguousTimeError:
pass
# Step 2: Check if result of (now - DST) is ambiguous.
check = now - now_dst
check_result = find_next_time_expression_time(check, seconds, minutes, hours)
try:
tzinfo.localize(check_result.replace(tzinfo=None), is_dst=None)
return result
except pytzexceptions.AmbiguousTimeError:
pass
# OK, edge case does apply. We must override the DST to DST-off
check_result = tzinfo.localize(check_result.replace(tzinfo=None), is_dst=False)
return check_result
return result

View file

@ -15,7 +15,7 @@ PyJWT==1.7.1
cryptography==3.3.2
pip>=8.0.3,<20.3
python-slugify==4.0.1
pytz>=2021.1
python-dateutil==2.8.1
pyyaml==5.4.1
requests==2.25.1
ruamel.yaml==0.15.100

View file

@ -47,7 +47,7 @@ REQUIRES = [
"cryptography==3.3.2",
"pip>=8.0.3,<20.3",
"python-slugify==4.0.1",
"pytz>=2021.1",
"python-dateutil==2.8.1",
"pyyaml==5.4.1",
"requests==2.25.1",
"ruamel.yaml==0.15.100",

View file

@ -270,7 +270,7 @@ async def async_test_home_assistant(loop, load_registries=True):
hass.config.latitude = 32.87336
hass.config.longitude = -117.22743
hass.config.elevation = 0
hass.config.time_zone = date_util.get_time_zone("US/Pacific")
hass.config.time_zone = "US/Pacific"
hass.config.units = METRIC_SYSTEM
hass.config.media_dirs = {"local": get_test_config_dir("media")}
hass.config.skip_pip = True

View file

@ -7,7 +7,6 @@ from typing import Any
from unittest.mock import patch
import pytest
import pytz
from homeassistant.components.climacell.config_flow import (
_get_config_schema,
@ -18,6 +17,7 @@ from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import ATTR_ATTRIBUTION
from homeassistant.core import HomeAssistant, State, callback
from homeassistant.helpers.entity_registry import async_get
from homeassistant.util import dt as dt_util
from .const import API_V3_ENTRY_DATA, API_V4_ENTRY_DATA
@ -59,7 +59,7 @@ async def _setup(hass: HomeAssistant, config: dict[str, Any]) -> State:
"""Set up entry and return entity state."""
with patch(
"homeassistant.util.dt.utcnow",
return_value=datetime(2021, 3, 6, 23, 59, 59, tzinfo=pytz.UTC),
return_value=datetime(2021, 3, 6, 23, 59, 59, tzinfo=dt_util.UTC),
):
data = _get_config_schema(hass)(config)
config_entry = MockConfigEntry(

View file

@ -7,7 +7,6 @@ from typing import Any
from unittest.mock import patch
import pytest
import pytz
from homeassistant.components.climacell.config_flow import (
_get_config_schema,
@ -46,6 +45,7 @@ from homeassistant.components.weather import (
from homeassistant.const import ATTR_ATTRIBUTION, ATTR_FRIENDLY_NAME
from homeassistant.core import HomeAssistant, State, callback
from homeassistant.helpers.entity_registry import async_get
from homeassistant.util import dt as dt_util
from .const import API_V3_ENTRY_DATA, API_V4_ENTRY_DATA
@ -70,7 +70,7 @@ async def _setup(hass: HomeAssistant, config: dict[str, Any]) -> State:
"""Set up entry and return entity state."""
with patch(
"homeassistant.util.dt.utcnow",
return_value=datetime(2021, 3, 6, 23, 59, 59, tzinfo=pytz.UTC),
return_value=datetime(2021, 3, 6, 23, 59, 59, tzinfo=dt_util.UTC),
):
data = _get_config_schema(hass)(config)
config_entry = MockConfigEntry(

View file

@ -57,7 +57,7 @@ async def test_websocket_core_update(hass, client):
assert hass.config.elevation != 25
assert hass.config.location_name != "Huis"
assert hass.config.units.name != CONF_UNIT_SYSTEM_IMPERIAL
assert hass.config.time_zone.zone != "America/New_York"
assert hass.config.time_zone != "America/New_York"
assert hass.config.external_url != "https://www.example.com"
assert hass.config.internal_url != "http://example.com"
@ -91,7 +91,7 @@ async def test_websocket_core_update(hass, client):
assert hass.config.internal_url == "http://example.local"
assert len(mock_set_tz.mock_calls) == 1
assert mock_set_tz.mock_calls[0][1][0].zone == "America/New_York"
assert mock_set_tz.mock_calls[0][1][0] == dt_util.get_time_zone("America/New_York")
async def test_websocket_core_update_not_admin(hass, hass_ws_client, hass_admin_user):

View file

@ -4,7 +4,6 @@ from os import path
from unittest.mock import patch
import pytest
import pytz
import voluptuous as vol
from homeassistant import config as hass_config
@ -37,6 +36,7 @@ import homeassistant.core as ha
from homeassistant.core import DOMAIN as HASS_DOMAIN, CoreState, State, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from homeassistant.util.unit_system import METRIC_SYSTEM
from tests.common import (
@ -691,9 +691,7 @@ async def test_temp_change_ac_trigger_on_not_long_enough(hass, setup_comp_4):
async def test_temp_change_ac_trigger_on_long_enough(hass, setup_comp_4):
"""Test if temperature change turn ac on."""
fake_changed = datetime.datetime(
1918, 11, 11, 11, 11, 11, tzinfo=datetime.timezone.utc
)
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC)
with patch(
"homeassistant.helpers.condition.dt_util.utcnow", return_value=fake_changed
):
@ -719,9 +717,7 @@ async def test_temp_change_ac_trigger_off_not_long_enough(hass, setup_comp_4):
async def test_temp_change_ac_trigger_off_long_enough(hass, setup_comp_4):
"""Test if temperature change turn ac on."""
fake_changed = datetime.datetime(
1918, 11, 11, 11, 11, 11, tzinfo=datetime.timezone.utc
)
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC)
with patch(
"homeassistant.helpers.condition.dt_util.utcnow", return_value=fake_changed
):
@ -801,9 +797,7 @@ async def test_temp_change_ac_trigger_on_not_long_enough_2(hass, setup_comp_5):
async def test_temp_change_ac_trigger_on_long_enough_2(hass, setup_comp_5):
"""Test if temperature change turn ac on."""
fake_changed = datetime.datetime(
1918, 11, 11, 11, 11, 11, tzinfo=datetime.timezone.utc
)
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC)
with patch(
"homeassistant.helpers.condition.dt_util.utcnow", return_value=fake_changed
):
@ -829,9 +823,7 @@ async def test_temp_change_ac_trigger_off_not_long_enough_2(hass, setup_comp_5):
async def test_temp_change_ac_trigger_off_long_enough_2(hass, setup_comp_5):
"""Test if temperature change turn ac on."""
fake_changed = datetime.datetime(
1918, 11, 11, 11, 11, 11, tzinfo=datetime.timezone.utc
)
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC)
with patch(
"homeassistant.helpers.condition.dt_util.utcnow", return_value=fake_changed
):
@ -919,9 +911,7 @@ async def test_temp_change_heater_trigger_on_not_long_enough(hass, setup_comp_6)
async def test_temp_change_heater_trigger_on_long_enough(hass, setup_comp_6):
"""Test if temperature change turn heater on after min cycle."""
fake_changed = datetime.datetime(
1918, 11, 11, 11, 11, 11, tzinfo=datetime.timezone.utc
)
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC)
with patch(
"homeassistant.helpers.condition.dt_util.utcnow", return_value=fake_changed
):
@ -938,9 +928,7 @@ async def test_temp_change_heater_trigger_on_long_enough(hass, setup_comp_6):
async def test_temp_change_heater_trigger_off_long_enough(hass, setup_comp_6):
"""Test if temperature change turn heater off after min cycle."""
fake_changed = datetime.datetime(
1918, 11, 11, 11, 11, 11, tzinfo=datetime.timezone.utc
)
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC)
with patch(
"homeassistant.helpers.condition.dt_util.utcnow", return_value=fake_changed
):
@ -1019,7 +1007,7 @@ async def test_temp_change_ac_trigger_on_long_enough_3(hass, setup_comp_7):
_setup_sensor(hass, 30)
await hass.async_block_till_done()
await common.async_set_temperature(hass, 25)
test_time = datetime.datetime.now(pytz.UTC)
test_time = datetime.datetime.now(dt_util.UTC)
async_fire_time_changed(hass, test_time)
await hass.async_block_till_done()
assert len(calls) == 0
@ -1042,7 +1030,7 @@ async def test_temp_change_ac_trigger_off_long_enough_3(hass, setup_comp_7):
_setup_sensor(hass, 20)
await hass.async_block_till_done()
await common.async_set_temperature(hass, 25)
test_time = datetime.datetime.now(pytz.UTC)
test_time = datetime.datetime.now(dt_util.UTC)
async_fire_time_changed(hass, test_time)
await hass.async_block_till_done()
assert len(calls) == 0
@ -1090,7 +1078,7 @@ async def test_temp_change_heater_trigger_on_long_enough_2(hass, setup_comp_8):
_setup_sensor(hass, 20)
await hass.async_block_till_done()
await common.async_set_temperature(hass, 25)
test_time = datetime.datetime.now(pytz.UTC)
test_time = datetime.datetime.now(dt_util.UTC)
async_fire_time_changed(hass, test_time)
await hass.async_block_till_done()
assert len(calls) == 0
@ -1113,7 +1101,7 @@ async def test_temp_change_heater_trigger_off_long_enough_2(hass, setup_comp_8):
_setup_sensor(hass, 30)
await hass.async_block_till_done()
await common.async_set_temperature(hass, 25)
test_time = datetime.datetime.now(pytz.UTC)
test_time = datetime.datetime.now(dt_util.UTC)
async_fire_time_changed(hass, test_time)
await hass.async_block_till_done()
assert len(calls) == 0

View file

@ -6,7 +6,6 @@ import unittest
from unittest.mock import patch
import pytest
import pytz
from homeassistant import config as hass_config
from homeassistant.components.history_stats import DOMAIN
@ -82,7 +81,7 @@ class TestHistoryStatsSensor(unittest.TestCase):
)
def test_period_parsing(self, mock):
"""Test the conversion from templates to period."""
now = datetime(2019, 1, 1, 23, 30, 0, tzinfo=pytz.utc)
now = datetime(2019, 1, 1, 23, 30, 0, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
today = Template(
"{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}",

View file

@ -26,7 +26,9 @@ def make_nyc_test_params(dtime, results, havdalah_offset=0):
if isinstance(results, dict):
time_zone = dt_util.get_time_zone("America/New_York")
results = {
key: time_zone.localize(value) if isinstance(value, datetime) else value
key: value.replace(tzinfo=time_zone)
if isinstance(value, datetime)
else value
for key, value in results.items()
}
return (
@ -46,7 +48,9 @@ def make_jerusalem_test_params(dtime, results, havdalah_offset=0):
if isinstance(results, dict):
time_zone = dt_util.get_time_zone("Asia/Jerusalem")
results = {
key: time_zone.localize(value) if isinstance(value, datetime) else value
key: value.replace(tzinfo=time_zone)
if isinstance(value, datetime)
else value
for key, value in results.items()
}
return (

View file

@ -179,9 +179,9 @@ async def test_issur_melacha_sensor(
):
"""Test Issur Melacha sensor output."""
time_zone = dt_util.get_time_zone(tzname)
test_time = time_zone.localize(now)
test_time = now.replace(tzinfo=time_zone)
hass.config.time_zone = time_zone
hass.config.time_zone = tzname
hass.config.latitude = latitude
hass.config.longitude = longitude
@ -214,7 +214,7 @@ async def test_issur_melacha_sensor(
[
latitude,
longitude,
time_zone,
tzname,
HDATE_DEFAULT_ALTITUDE,
diaspora,
"english",
@ -270,9 +270,9 @@ async def test_issur_melacha_sensor_update(
):
"""Test Issur Melacha sensor output."""
time_zone = dt_util.get_time_zone(tzname)
test_time = time_zone.localize(now)
test_time = now.replace(tzinfo=time_zone)
hass.config.time_zone = time_zone
hass.config.time_zone = tzname
hass.config.latitude = latitude
hass.config.longitude = longitude

View file

@ -163,9 +163,9 @@ async def test_jewish_calendar_sensor(
):
"""Test Jewish calendar sensor output."""
time_zone = dt_util.get_time_zone(tzname)
test_time = time_zone.localize(now)
test_time = now.replace(tzinfo=time_zone)
hass.config.time_zone = time_zone
hass.config.time_zone = tzname
hass.config.latitude = latitude
hass.config.longitude = longitude
@ -188,7 +188,9 @@ async def test_jewish_calendar_sensor(
await hass.async_block_till_done()
result = (
dt_util.as_utc(time_zone.localize(result)) if isinstance(result, dt) else result
dt_util.as_utc(result.replace(tzinfo=time_zone))
if isinstance(result, dt)
else result
)
sensor_object = hass.states.get(f"sensor.test_{sensor}")
@ -506,9 +508,9 @@ async def test_shabbat_times_sensor(
):
"""Test sensor output for upcoming shabbat/yomtov times."""
time_zone = dt_util.get_time_zone(tzname)
test_time = time_zone.localize(now)
test_time = now.replace(tzinfo=time_zone)
hass.config.time_zone = time_zone
hass.config.time_zone = tzname
hass.config.latitude = latitude
hass.config.longitude = longitude
@ -559,7 +561,7 @@ async def test_shabbat_times_sensor(
[
latitude,
longitude,
time_zone,
tzname,
HDATE_DEFAULT_ALTITUDE,
diaspora,
language,
@ -593,7 +595,7 @@ OMER_TEST_IDS = [
@pytest.mark.parametrize(["test_time", "result"], OMER_PARAMS, ids=OMER_TEST_IDS)
async def test_omer_sensor(hass, legacy_patchable_time, test_time, result):
"""Test Omer Count sensor output."""
test_time = hass.config.time_zone.localize(test_time)
test_time = test_time.replace(tzinfo=dt_util.get_time_zone(hass.config.time_zone))
with alter_time(test_time):
assert await async_setup_component(
@ -627,7 +629,7 @@ DAFYOMI_TEST_IDS = [
@pytest.mark.parametrize(["test_time", "result"], DAFYOMI_PARAMS, ids=DAFYOMI_TEST_IDS)
async def test_dafyomi_sensor(hass, legacy_patchable_time, test_time, result):
"""Test Daf Yomi sensor output."""
test_time = hass.config.time_zone.localize(test_time)
test_time = test_time.replace(tzinfo=dt_util.get_time_zone(hass.config.time_zone))
with alter_time(test_time):
assert await async_setup_component(

View file

@ -2,12 +2,11 @@
from datetime import datetime
from unittest.mock import patch
from pytz import timezone
from homeassistant import config_entries, data_entry_flow
from homeassistant.components.pvpc_hourly_pricing import ATTR_TARIFF, DOMAIN
from homeassistant.const import CONF_NAME
from homeassistant.helpers import entity_registry as er
from homeassistant.util import dt as dt_util
from .conftest import check_valid_state
@ -26,7 +25,7 @@ async def test_config_flow(
- Check abort when trying to config another with same tariff
- Check removal and add again to check state restoration
"""
hass.config.time_zone = timezone("Europe/Madrid")
hass.config.time_zone = dt_util.get_time_zone("Europe/Madrid")
mock_data = {"return_time": datetime(2019, 10, 26, 14, 0, tzinfo=date_util.UTC)}
def mock_now():

View file

@ -3,12 +3,11 @@ from datetime import datetime, timedelta
import logging
from unittest.mock import patch
from pytz import timezone
from homeassistant.components.pvpc_hourly_pricing import ATTR_TARIFF, DOMAIN
from homeassistant.const import CONF_NAME
from homeassistant.core import ATTR_NOW, EVENT_TIME_CHANGED
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from .conftest import check_valid_state
@ -32,7 +31,7 @@ async def test_sensor_availability(
hass, caplog, legacy_patchable_time, pvpc_aioclient_mock: AiohttpClientMocker
):
"""Test sensor availability and handling of cloud access."""
hass.config.time_zone = timezone("Europe/Madrid")
hass.config.time_zone = dt_util.get_time_zone("Europe/Madrid")
config = {DOMAIN: [{CONF_NAME: "test_dst", ATTR_TARIFF: "discrimination"}]}
mock_data = {"return_time": datetime(2019, 10, 27, 20, 0, 0, tzinfo=date_util.UTC)}

View file

@ -170,5 +170,5 @@ def _process_timestamp(ts):
if ts is None:
return None
if ts.tzinfo is None:
return dt_util.UTC.localize(ts)
return ts.replace(tzinfo=dt_util.UTC)
return dt_util.as_utc(ts)

View file

@ -604,7 +604,7 @@ def test_auto_purge(hass_recorder):
#
# The clock is started at 4:15am then advanced forward below
now = dt_util.utcnow()
test_time = tz.localize(datetime(now.year + 2, 1, 1, 4, 15, 0))
test_time = datetime(now.year + 2, 1, 1, 4, 15, 0, tzinfo=tz)
run_tasks_at_time(hass, test_time)
with patch(

View file

@ -2,7 +2,6 @@
from datetime import datetime
import pytest
import pytz
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
@ -144,11 +143,11 @@ async def test_process_timestamp():
"""Test processing time stamp to UTC."""
datetime_with_tzinfo = datetime(2016, 7, 9, 11, 0, 0, tzinfo=dt.UTC)
datetime_without_tzinfo = datetime(2016, 7, 9, 11, 0, 0)
est = pytz.timezone("US/Eastern")
est = dt_util.get_time_zone("US/Eastern")
datetime_est_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=est)
nst = pytz.timezone("Canada/Newfoundland")
nst = dt_util.get_time_zone("Canada/Newfoundland")
datetime_nst_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=nst)
hst = pytz.timezone("US/Hawaii")
hst = dt_util.get_time_zone("US/Hawaii")
datetime_hst_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=hst)
assert process_timestamp(datetime_with_tzinfo) == datetime(
@ -158,13 +157,13 @@ async def test_process_timestamp():
2016, 7, 9, 11, 0, 0, tzinfo=dt.UTC
)
assert process_timestamp(datetime_est_timezone) == datetime(
2016, 7, 9, 15, 56, tzinfo=dt.UTC
2016, 7, 9, 15, 0, tzinfo=dt.UTC
)
assert process_timestamp(datetime_nst_timezone) == datetime(
2016, 7, 9, 14, 31, tzinfo=dt.UTC
2016, 7, 9, 13, 30, tzinfo=dt.UTC
)
assert process_timestamp(datetime_hst_timezone) == datetime(
2016, 7, 9, 21, 31, tzinfo=dt.UTC
2016, 7, 9, 21, 0, tzinfo=dt.UTC
)
assert process_timestamp(None) is None
@ -173,13 +172,13 @@ async def test_process_timestamp_to_utc_isoformat():
"""Test processing time stamp to UTC isoformat."""
datetime_with_tzinfo = datetime(2016, 7, 9, 11, 0, 0, tzinfo=dt.UTC)
datetime_without_tzinfo = datetime(2016, 7, 9, 11, 0, 0)
est = pytz.timezone("US/Eastern")
est = dt_util.get_time_zone("US/Eastern")
datetime_est_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=est)
est = pytz.timezone("US/Eastern")
est = dt_util.get_time_zone("US/Eastern")
datetime_est_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=est)
nst = pytz.timezone("Canada/Newfoundland")
nst = dt_util.get_time_zone("Canada/Newfoundland")
datetime_nst_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=nst)
hst = pytz.timezone("US/Hawaii")
hst = dt_util.get_time_zone("US/Hawaii")
datetime_hst_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=hst)
assert (
@ -192,15 +191,15 @@ async def test_process_timestamp_to_utc_isoformat():
)
assert (
process_timestamp_to_utc_isoformat(datetime_est_timezone)
== "2016-07-09T15:56:00+00:00"
== "2016-07-09T15:00:00+00:00"
)
assert (
process_timestamp_to_utc_isoformat(datetime_nst_timezone)
== "2016-07-09T14:31:00+00:00"
== "2016-07-09T13:30:00+00:00"
)
assert (
process_timestamp_to_utc_isoformat(datetime_hst_timezone)
== "2016-07-09T21:31:00+00:00"
== "2016-07-09T21:00:00+00:00"
)
assert process_timestamp_to_utc_isoformat(None) is None

View file

@ -33,7 +33,7 @@ def calls(hass):
def setup_comp(hass):
"""Initialize components."""
mock_component(hass, "group")
dt_util.set_default_time_zone(hass.config.time_zone)
hass.config.set_time_zone(hass.config.time_zone)
hass.loop.run_until_complete(
async_setup_component(hass, sun.DOMAIN, {sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
)

View file

@ -3,7 +3,6 @@ from datetime import datetime, timedelta
from unittest.mock import patch
import pytest
import pytz
from homeassistant.const import STATE_OFF, STATE_ON
import homeassistant.core as ha
@ -61,7 +60,7 @@ async def test_setup_no_sensors(hass):
async def test_in_period_on_start(hass):
"""Test simple setting."""
test_time = datetime(2019, 1, 10, 18, 43, 0, tzinfo=hass.config.time_zone)
test_time = datetime(2019, 1, 10, 18, 43, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{
@ -85,7 +84,7 @@ async def test_in_period_on_start(hass):
async def test_midnight_turnover_before_midnight_inside_period(hass):
"""Test midnight turnover setting before midnight inside period ."""
test_time = datetime(2019, 1, 10, 22, 30, 0, tzinfo=hass.config.time_zone)
test_time = datetime(2019, 1, 10, 22, 30, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{"platform": "tod", "name": "Night", "after": "22:00", "before": "5:00"}
@ -104,9 +103,7 @@ async def test_midnight_turnover_before_midnight_inside_period(hass):
async def test_midnight_turnover_after_midnight_inside_period(hass):
"""Test midnight turnover setting before midnight inside period ."""
test_time = hass.config.time_zone.localize(
datetime(2019, 1, 10, 21, 0, 0)
).astimezone(pytz.UTC)
test_time = datetime(2019, 1, 10, 21, 0, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{"platform": "tod", "name": "Night", "after": "22:00", "before": "5:00"}
@ -140,9 +137,7 @@ async def test_midnight_turnover_after_midnight_inside_period(hass):
async def test_midnight_turnover_before_midnight_outside_period(hass):
"""Test midnight turnover setting before midnight outside period."""
test_time = hass.config.time_zone.localize(
datetime(2019, 1, 10, 20, 30, 0)
).astimezone(pytz.UTC)
test_time = datetime(2019, 1, 10, 20, 30, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{"platform": "tod", "name": "Night", "after": "22:00", "before": "5:00"}
@ -161,9 +156,7 @@ async def test_midnight_turnover_before_midnight_outside_period(hass):
async def test_midnight_turnover_after_midnight_outside_period(hass):
"""Test midnight turnover setting before midnight inside period ."""
test_time = hass.config.time_zone.localize(
datetime(2019, 1, 10, 20, 0, 0)
).astimezone(pytz.UTC)
test_time = datetime(2019, 1, 10, 20, 0, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
@ -180,9 +173,7 @@ async def test_midnight_turnover_after_midnight_outside_period(hass):
state = hass.states.get("binary_sensor.night")
assert state.state == STATE_OFF
switchover_time = hass.config.time_zone.localize(
datetime(2019, 1, 11, 4, 59, 0)
).astimezone(pytz.UTC)
switchover_time = datetime(2019, 1, 11, 4, 59, 0, tzinfo=dt_util.UTC)
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=switchover_time,
@ -210,9 +201,7 @@ async def test_midnight_turnover_after_midnight_outside_period(hass):
async def test_from_sunrise_to_sunset(hass):
"""Test period from sunrise to sunset."""
test_time = hass.config.time_zone.localize(datetime(2019, 1, 12)).astimezone(
pytz.UTC
)
test_time = datetime(2019, 1, 12, tzinfo=dt_util.UTC)
sunrise = dt_util.as_local(
get_astral_event_date(hass, "sunrise", dt_util.as_utc(test_time))
)
@ -311,9 +300,7 @@ async def test_from_sunrise_to_sunset(hass):
async def test_from_sunset_to_sunrise(hass):
"""Test period from sunset to sunrise."""
test_time = hass.config.time_zone.localize(datetime(2019, 1, 12)).astimezone(
pytz.UTC
)
test_time = datetime(2019, 1, 12, tzinfo=dt_util.UTC)
sunset = dt_util.as_local(get_astral_event_date(hass, "sunset", test_time))
sunrise = dt_util.as_local(get_astral_event_next(hass, "sunrise", sunset))
# assert sunset == sunrise
@ -405,13 +392,13 @@ async def test_from_sunset_to_sunrise(hass):
async def test_offset(hass):
"""Test offset."""
after = hass.config.time_zone.localize(datetime(2019, 1, 10, 18, 0, 0)).astimezone(
pytz.UTC
) + timedelta(hours=1, minutes=34)
after = datetime(2019, 1, 10, 18, 0, 0, tzinfo=dt_util.UTC) + timedelta(
hours=1, minutes=34
)
before = hass.config.time_zone.localize(datetime(2019, 1, 10, 22, 0, 0)).astimezone(
pytz.UTC
) + timedelta(hours=1, minutes=45)
before = datetime(2019, 1, 10, 22, 0, 0, tzinfo=dt_util.UTC) + timedelta(
hours=1, minutes=45
)
entity_id = "binary_sensor.evening"
config = {
@ -484,9 +471,9 @@ async def test_offset(hass):
async def test_offset_overnight(hass):
"""Test offset overnight."""
after = hass.config.time_zone.localize(datetime(2019, 1, 10, 18, 0, 0)).astimezone(
pytz.UTC
) + timedelta(hours=1, minutes=34)
after = datetime(2019, 1, 10, 18, 0, 0, tzinfo=dt_util.UTC) + timedelta(
hours=1, minutes=34
)
entity_id = "binary_sensor.evening"
config = {
"binary_sensor": [
@ -528,9 +515,7 @@ async def test_norwegian_case_winter(hass):
hass.config.latitude = 69.6
hass.config.longitude = 18.8
test_time = hass.config.time_zone.localize(datetime(2010, 1, 1)).astimezone(
pytz.UTC
)
test_time = datetime(2010, 1, 1, tzinfo=dt_util.UTC)
sunrise = dt_util.as_local(
get_astral_event_next(hass, "sunrise", dt_util.as_utc(test_time))
)
@ -645,9 +630,7 @@ async def test_norwegian_case_summer(hass):
hass.config.longitude = 18.8
hass.config.elevation = 10.0
test_time = hass.config.time_zone.localize(datetime(2010, 6, 1)).astimezone(
pytz.UTC
)
test_time = datetime(2010, 6, 1, tzinfo=dt_util.UTC)
sunrise = dt_util.as_local(
get_astral_event_next(hass, "sunrise", dt_util.as_utc(test_time))
@ -759,9 +742,7 @@ async def test_norwegian_case_summer(hass):
async def test_sun_offset(hass):
"""Test sun event with offset."""
test_time = hass.config.time_zone.localize(datetime(2019, 1, 12)).astimezone(
pytz.UTC
)
test_time = datetime(2019, 1, 12, tzinfo=dt_util.UTC)
sunrise = dt_util.as_local(
get_astral_event_date(hass, "sunrise", dt_util.as_utc(test_time))
+ timedelta(hours=-1, minutes=-30)
@ -881,30 +862,27 @@ async def test_sun_offset(hass):
async def test_dst(hass):
"""Test sun event with offset."""
hass.config.time_zone = pytz.timezone("CET")
test_time = hass.config.time_zone.localize(
datetime(2019, 3, 30, 3, 0, 0)
).astimezone(pytz.UTC)
hass.config.time_zone = "CET"
test_time = datetime(2019, 3, 30, 3, 0, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{"platform": "tod", "name": "Day", "after": "2:30", "before": "2:40"}
]
}
# Test DST:
# after 2019-03-30 03:00 CET the next update should ge scheduled
# at 3:30 not 2:30 local time
# Internally the
entity_id = "binary_sensor.day"
testtime = test_time
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=testtime,
return_value=test_time,
):
await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state.attributes["after"] == "2019-03-31T03:30:00+02:00"
assert state.attributes["before"] == "2019-03-31T03:40:00+02:00"
assert state.attributes["next_update"] == "2019-03-31T03:30:00+02:00"
assert state.attributes["after"] == "2019-03-30T03:30:00+01:00"
assert state.attributes["before"] == "2019-03-30T03:40:00+01:00"
assert state.attributes["next_update"] == "2019-03-30T03:30:00+01:00"
assert state.state == STATE_OFF

View file

@ -7,7 +7,6 @@ from urllib.parse import urlparse
from aiohttp.test_utils import TestClient
import arrow
import pytz
from withings_api.common import (
MeasureGetMeasResponse,
NotifyAppli,
@ -40,6 +39,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_entry_oauth2_flow
from homeassistant.helpers.config_entry_oauth2_flow import AUTH_CALLBACK_PATH
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from tests.test_util.aiohttp import AiohttpClientMocker
@ -77,7 +77,7 @@ def new_profile_config(
measuregrps=[],
more=False,
offset=0,
timezone=pytz.UTC,
timezone=dt_util.UTC,
updatetime=arrow.get(12345),
),
api_response_sleep_get_summary=api_response_sleep_get_summary

View file

@ -3,7 +3,6 @@ from typing import Any
from unittest.mock import patch
import arrow
import pytz
from withings_api.common import (
GetSleepSummaryData,
GetSleepSummarySerie,
@ -29,6 +28,7 @@ from homeassistant.components.withings.const import Measurement
from homeassistant.core import HomeAssistant, State
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_registry import EntityRegistry
from homeassistant.util import dt as dt_util
from .common import ComponentFactory, new_profile_config
@ -189,7 +189,7 @@ PERSON0 = new_profile_config(
),
),
more=False,
timezone=pytz.UTC,
timezone=dt_util.UTC,
updatetime=arrow.get("2019-08-01"),
offset=0,
),
@ -198,7 +198,7 @@ PERSON0 = new_profile_config(
offset=0,
series=(
GetSleepSummarySerie(
timezone=pytz.UTC,
timezone=dt_util.UTC,
model=SleepModel.SLEEP_MONITOR,
startdate=arrow.get("2019-02-01"),
enddate=arrow.get("2019-02-01"),
@ -225,7 +225,7 @@ PERSON0 = new_profile_config(
),
),
GetSleepSummarySerie(
timezone=pytz.UTC,
timezone=dt_util.UTC,
model=SleepModel.SLEEP_MONITOR,
startdate=arrow.get("2019-02-01"),
enddate=arrow.get("2019-02-01"),

View file

@ -5,7 +5,6 @@ from unittest.mock import MagicMock, patch
from miio import DeviceException
import pytest
from pytz import utc
from homeassistant.components.vacuum import (
ATTR_BATTERY_ICON,
@ -55,6 +54,7 @@ from homeassistant.const import (
STATE_ON,
STATE_UNAVAILABLE,
)
from homeassistant.util import dt as dt_util
from .test_config_flow import TEST_MAC
@ -106,12 +106,12 @@ def mirobo_is_got_error_fixture():
mock_timer_1 = MagicMock()
mock_timer_1.enabled = True
mock_timer_1.cron = "5 5 1 8 1"
mock_timer_1.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc)
mock_timer_1.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=dt_util.UTC)
mock_timer_2 = MagicMock()
mock_timer_2.enabled = False
mock_timer_2.cron = "5 5 1 8 2"
mock_timer_2.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc)
mock_timer_2.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=dt_util.UTC)
mock_vacuum.timer.return_value = [mock_timer_1, mock_timer_2]
@ -180,12 +180,12 @@ def mirobo_is_on_fixture():
mock_timer_1 = MagicMock()
mock_timer_1.enabled = True
mock_timer_1.cron = "5 5 1 8 1"
mock_timer_1.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc)
mock_timer_1.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=dt_util.UTC)
mock_timer_2 = MagicMock()
mock_timer_2.enabled = False
mock_timer_2.cron = "5 5 1 8 2"
mock_timer_2.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc)
mock_timer_2.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=dt_util.UTC)
mock_vacuum.timer.return_value = [mock_timer_1, mock_timer_2]
@ -255,12 +255,12 @@ async def test_xiaomi_vacuum_services(hass, caplog, mock_mirobo_is_got_error):
{
"enabled": True,
"cron": "5 5 1 8 1",
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc),
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=dt_util.UTC),
},
{
"enabled": False,
"cron": "5 5 1 8 2",
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc),
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=dt_util.UTC),
},
]
@ -353,12 +353,12 @@ async def test_xiaomi_specific_services(hass, caplog, mock_mirobo_is_on):
{
"enabled": True,
"cron": "5 5 1 8 1",
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc),
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=dt_util.UTC),
},
{
"enabled": False,
"cron": "5 5 1 8 2",
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc),
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=dt_util.UTC),
},
]

View file

@ -5,7 +5,6 @@ from datetime import datetime
from unittest.mock import MagicMock, patch
import pytest
from pytz import utc
import voluptuous as vol
from homeassistant.bootstrap import async_setup_component
@ -19,6 +18,7 @@ from homeassistant.components.zwave import (
from homeassistant.components.zwave.binary_sensor import get_device
from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.util import dt as dt_util
from tests.common import async_fire_time_changed, mock_registry
from tests.mock.zwave import MockEntityValues, MockNetwork, MockNode, MockValue
@ -140,7 +140,7 @@ async def test_auto_heal_midnight(hass, mock_openzwave, legacy_patchable_time):
network = hass.data[zwave.DATA_NETWORK]
assert not network.heal.called
time = utc.localize(datetime(2017, 5, 6, 0, 0, 0))
time = datetime(2017, 5, 6, 0, 0, 0, tzinfo=dt_util.UTC)
async_fire_time_changed(hass, time)
await hass.async_block_till_done()
await hass.async_block_till_done()
@ -156,7 +156,7 @@ async def test_auto_heal_disabled(hass, mock_openzwave):
network = hass.data[zwave.DATA_NETWORK]
assert not network.heal.called
time = utc.localize(datetime(2017, 5, 6, 0, 0, 0))
time = datetime(2017, 5, 6, 0, 0, 0, tzinfo=dt_util.UTC)
async_fire_time_changed(hass, time)
await hass.async_block_till_done()
assert not network.heal.called

View file

@ -27,7 +27,7 @@ def calls(hass):
@pytest.fixture(autouse=True)
def setup_comp(hass):
"""Initialize components."""
dt_util.set_default_time_zone(hass.config.time_zone)
hass.config.set_time_zone(hass.config.time_zone)
hass.loop.run_until_complete(
async_setup_component(hass, sun.DOMAIN, {sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
)

View file

@ -2908,8 +2908,8 @@ async def test_periodic_task_entering_dst(hass):
specific_runs = []
now = dt_util.utcnow()
time_that_will_not_match_right_away = timezone.localize(
datetime(now.year + 1, 3, 25, 2, 31, 0)
time_that_will_not_match_right_away = datetime(
now.year + 1, 3, 25, 2, 31, 0, tzinfo=timezone
)
with patch(
@ -2924,25 +2924,25 @@ async def test_periodic_task_entering_dst(hass):
)
async_fire_time_changed(
hass, timezone.localize(datetime(now.year + 1, 3, 25, 1, 50, 0, 999999))
hass, datetime(now.year + 1, 3, 25, 1, 50, 0, 999999, tzinfo=timezone)
)
await hass.async_block_till_done()
assert len(specific_runs) == 0
async_fire_time_changed(
hass, timezone.localize(datetime(now.year + 1, 3, 25, 3, 50, 0, 999999))
hass, datetime(now.year + 1, 3, 25, 3, 50, 0, 999999, tzinfo=timezone)
)
await hass.async_block_till_done()
assert len(specific_runs) == 0
async_fire_time_changed(
hass, timezone.localize(datetime(now.year + 1, 3, 26, 1, 50, 0, 999999))
hass, datetime(now.year + 1, 3, 26, 1, 50, 0, 999999, tzinfo=timezone)
)
await hass.async_block_till_done()
assert len(specific_runs) == 0
async_fire_time_changed(
hass, timezone.localize(datetime(now.year + 1, 3, 26, 2, 50, 0, 999999))
hass, datetime(now.year + 1, 3, 26, 2, 50, 0, 999999, tzinfo=timezone)
)
await hass.async_block_till_done()
assert len(specific_runs) == 1
@ -2958,8 +2958,8 @@ async def test_periodic_task_leaving_dst(hass):
now = dt_util.utcnow()
time_that_will_not_match_right_away = timezone.localize(
datetime(now.year + 1, 10, 28, 2, 28, 0), is_dst=True
time_that_will_not_match_right_away = datetime(
now.year + 1, 10, 28, 2, 28, 0, tzinfo=timezone, fold=1
)
with patch(
@ -2974,46 +2974,33 @@ async def test_periodic_task_leaving_dst(hass):
)
async_fire_time_changed(
hass,
timezone.localize(
datetime(now.year + 1, 10, 28, 2, 5, 0, 999999), is_dst=False
),
hass, datetime(now.year + 1, 10, 28, 2, 5, 0, 999999, tzinfo=timezone, fold=0)
)
await hass.async_block_till_done()
assert len(specific_runs) == 0
async_fire_time_changed(
hass,
timezone.localize(
datetime(now.year + 1, 10, 28, 2, 55, 0, 999999), is_dst=False
),
hass, datetime(now.year + 1, 10, 28, 2, 55, 0, 999999, tzinfo=timezone, fold=0)
)
await hass.async_block_till_done()
assert len(specific_runs) == 1
async_fire_time_changed(
hass,
timezone.localize(
datetime(now.year + 2, 10, 28, 2, 45, 0, 999999), is_dst=True
),
datetime(now.year + 2, 10, 28, 2, 45, 0, 999999, tzinfo=timezone, fold=1),
)
await hass.async_block_till_done()
assert len(specific_runs) == 2
async_fire_time_changed(
hass,
timezone.localize(
datetime(now.year + 2, 10, 28, 2, 55, 0, 999999), is_dst=True
),
datetime(now.year + 2, 10, 28, 2, 55, 0, 999999, tzinfo=timezone, fold=1),
)
await hass.async_block_till_done()
assert len(specific_runs) == 2
async_fire_time_changed(
hass,
timezone.localize(
datetime(now.year + 2, 10, 28, 2, 55, 0, 999999), is_dst=True
),
hass, datetime(now.year + 2, 10, 28, 2, 55, 0, 999999, tzinfo=timezone, fold=1)
)
await hass.async_block_till_done()
assert len(specific_runs) == 2
@ -3224,7 +3211,7 @@ async def test_async_track_point_in_time_cancel(hass):
await asyncio.sleep(0.2)
assert len(times) == 1
assert times[0].tzinfo.zone == "US/Hawaii"
assert "US/Hawaii" in str(times[0].tzinfo)
async def test_async_track_entity_registry_updated_event(hass):

View file

@ -5,7 +5,6 @@ import random
from unittest.mock import patch
import pytest
import pytz
import voluptuous as vol
from homeassistant.components import group
@ -763,7 +762,7 @@ def test_render_with_possible_json_value_non_string_value(hass):
hass,
)
value = datetime(2019, 1, 18, 12, 13, 14)
expected = str(pytz.utc.localize(value))
expected = str(value.replace(tzinfo=dt_util.UTC))
assert tpl.async_render_with_possible_json_value(value) == expected

View file

@ -374,7 +374,7 @@ async def test_loading_configuration_from_storage(hass, hass_storage):
assert hass.config.elevation == 10
assert hass.config.location_name == "Home"
assert hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
assert hass.config.time_zone.zone == "Europe/Copenhagen"
assert hass.config.time_zone == "Europe/Copenhagen"
assert hass.config.external_url == "https://www.example.com"
assert hass.config.internal_url == "http://example.local"
assert len(hass.config.allowlist_external_dirs) == 3
@ -405,7 +405,7 @@ async def test_loading_configuration_from_storage_with_yaml_only(hass, hass_stor
assert hass.config.elevation == 10
assert hass.config.location_name == "Home"
assert hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
assert hass.config.time_zone.zone == "Europe/Copenhagen"
assert hass.config.time_zone == "Europe/Copenhagen"
assert len(hass.config.allowlist_external_dirs) == 3
assert "/etc" in hass.config.allowlist_external_dirs
assert hass.config.media_dirs == {"mymedia": "/usr"}
@ -463,7 +463,7 @@ async def test_override_stored_configuration(hass, hass_storage):
assert hass.config.elevation == 10
assert hass.config.location_name == "Home"
assert hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
assert hass.config.time_zone.zone == "Europe/Copenhagen"
assert hass.config.time_zone == "Europe/Copenhagen"
assert len(hass.config.allowlist_external_dirs) == 3
assert "/etc" in hass.config.allowlist_external_dirs
assert hass.config.config_source == config_util.SOURCE_YAML
@ -493,7 +493,7 @@ async def test_loading_configuration(hass):
assert hass.config.elevation == 25
assert hass.config.location_name == "Huis"
assert hass.config.units.name == CONF_UNIT_SYSTEM_IMPERIAL
assert hass.config.time_zone.zone == "America/New_York"
assert hass.config.time_zone == "America/New_York"
assert hass.config.external_url == "https://www.example.com"
assert hass.config.internal_url == "http://example.local"
assert len(hass.config.allowlist_external_dirs) == 3
@ -525,7 +525,7 @@ async def test_loading_configuration_temperature_unit(hass):
assert hass.config.elevation == 25
assert hass.config.location_name == "Huis"
assert hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
assert hass.config.time_zone.zone == "America/New_York"
assert hass.config.time_zone == "America/New_York"
assert hass.config.external_url == "https://www.example.com"
assert hass.config.internal_url == "http://example.local"
assert hass.config.config_source == config_util.SOURCE_YAML

View file

@ -9,7 +9,6 @@ from tempfile import TemporaryDirectory
from unittest.mock import MagicMock, Mock, PropertyMock, patch
import pytest
import pytz
import voluptuous as vol
from homeassistant.const import (
@ -44,7 +43,7 @@ from homeassistant.util.unit_system import METRIC_SYSTEM
from tests.common import async_capture_events, async_mock_service
PST = pytz.timezone("America/Los_Angeles")
PST = dt_util.get_time_zone("America/Los_Angeles")
def test_split_entity_id():
@ -877,7 +876,7 @@ def test_config_defaults():
assert config.longitude == 0
assert config.elevation == 0
assert config.location_name == "Home"
assert config.time_zone == dt_util.UTC
assert config.time_zone == "UTC"
assert config.internal_url is None
assert config.external_url is None
assert config.config_source == "default"

View file

@ -16,17 +16,12 @@ def teardown():
def test_get_time_zone_retrieves_valid_time_zone():
"""Test getting a time zone."""
time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)
assert time_zone is not None
assert time_zone.zone == TEST_TIME_ZONE
assert dt_util.get_time_zone(TEST_TIME_ZONE) is not None
def test_get_time_zone_returns_none_for_garbage_time_zone():
"""Test getting a non existing time zone."""
time_zone = dt_util.get_time_zone("Non existing time zone")
assert time_zone is None
assert dt_util.get_time_zone("Non existing time zone") is None
def test_set_default_time_zone():
@ -35,8 +30,7 @@ def test_set_default_time_zone():
dt_util.set_default_time_zone(time_zone)
# We cannot compare the timezones directly because of DST
assert time_zone.zone == dt_util.now().tzinfo.zone
assert dt_util.now().tzinfo is time_zone
def test_utcnow():
@ -239,35 +233,111 @@ def test_find_next_time_expression_time_dst():
return dt_util.find_next_time_expression_time(dt, seconds, minutes, hours)
# Entering DST, clocks are rolled forward
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == find(
tz.localize(datetime(2018, 3, 25, 1, 50, 0)), 2, 30, 0
assert datetime(2018, 3, 26, 2, 30, 0, tzinfo=tz) == find(
datetime(2018, 3, 25, 1, 50, 0, tzinfo=tz), 2, 30, 0
)
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == find(
tz.localize(datetime(2018, 3, 25, 3, 50, 0)), 2, 30, 0
assert datetime(2018, 3, 26, 2, 30, 0, tzinfo=tz) == find(
datetime(2018, 3, 25, 3, 50, 0, tzinfo=tz), 2, 30, 0
)
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == find(
tz.localize(datetime(2018, 3, 26, 1, 50, 0)), 2, 30, 0
assert datetime(2018, 3, 26, 2, 30, 0, tzinfo=tz) == find(
datetime(2018, 3, 26, 1, 50, 0, tzinfo=tz), 2, 30, 0
)
# Leaving DST, clocks are rolled back
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == find(
tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False), 2, 30, 0
assert datetime(2018, 10, 28, 2, 30, 0, tzinfo=tz, fold=0) == find(
datetime(2018, 10, 28, 2, 5, 0, tzinfo=tz, fold=0), 2, 30, 0
)
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == find(
tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True), 2, 30, 0
assert datetime(2018, 10, 28, 2, 30, 0, tzinfo=tz, fold=0) == find(
datetime(2018, 10, 28, 2, 5, 0, tzinfo=tz), 2, 30, 0
)
assert tz.localize(datetime(2018, 10, 28, 4, 30, 0), is_dst=False) == find(
tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True), 4, 30, 0
assert datetime(2018, 10, 28, 2, 30, 0, tzinfo=tz, fold=1) == find(
datetime(2018, 10, 28, 2, 55, 0, tzinfo=tz), 2, 30, 0
)
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=True) == find(
tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True), 2, 30, 0
assert datetime(2018, 10, 28, 2, 30, 0, tzinfo=tz, fold=1) == find(
datetime(2018, 10, 28, 2, 55, 0, tzinfo=tz, fold=0), 2, 30, 0
)
assert tz.localize(datetime(2018, 10, 29, 2, 30, 0)) == find(
tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False), 2, 30, 0
assert datetime(2018, 10, 28, 4, 30, 0, tzinfo=tz, fold=0) == find(
datetime(2018, 10, 28, 2, 55, 0, tzinfo=tz, fold=1), 4, 30, 0
)
assert datetime(2018, 10, 28, 2, 30, 0, tzinfo=tz, fold=1) == find(
datetime(2018, 10, 28, 2, 5, 0, tzinfo=tz, fold=1), 2, 30, 0
)
assert datetime(2018, 10, 28, 2, 30, 0, tzinfo=tz, fold=1) == find(
datetime(2018, 10, 28, 2, 55, 0, tzinfo=tz, fold=0), 2, 30, 0
)
def test_find_next_time_expression_time_dst_chicago():
"""Test daylight saving time for find_next_time_expression_time."""
tz = dt_util.get_time_zone("America/Chicago")
dt_util.set_default_time_zone(tz)
def find(dt, hour, minute, second):
"""Call test_find_next_time_expression_time."""
seconds = dt_util.parse_time_expression(second, 0, 59)
minutes = dt_util.parse_time_expression(minute, 0, 59)
hours = dt_util.parse_time_expression(hour, 0, 23)
return dt_util.find_next_time_expression_time(dt, seconds, minutes, hours)
# Entering DST, clocks are rolled forward
assert datetime(2021, 3, 15, 2, 30, 0, tzinfo=tz) == find(
datetime(2021, 3, 14, 1, 50, 0, tzinfo=tz), 2, 30, 0
)
assert datetime(2021, 3, 15, 2, 30, 0, tzinfo=tz) == find(
datetime(2021, 3, 14, 3, 50, 0, tzinfo=tz), 2, 30, 0
)
assert datetime(2021, 3, 15, 2, 30, 0, tzinfo=tz) == find(
datetime(2021, 3, 14, 1, 50, 0, tzinfo=tz), 2, 30, 0
)
assert datetime(2021, 3, 14, 3, 30, 0, tzinfo=tz) == find(
datetime(2021, 3, 14, 1, 50, 0, tzinfo=tz), 3, 30, 0
)
# Leaving DST, clocks are rolled back
assert datetime(2021, 11, 7, 2, 30, 0, tzinfo=tz, fold=0) == find(
datetime(2021, 11, 7, 2, 5, 0, tzinfo=tz, fold=0), 2, 30, 0
)
assert datetime(2021, 11, 7, 2, 30, 0, tzinfo=tz) == find(
datetime(2021, 11, 7, 2, 5, 0, tzinfo=tz), 2, 30, 0
)
assert datetime(2021, 11, 7, 2, 30, 0, tzinfo=tz, fold=0) == find(
datetime(2021, 11, 7, 2, 5, 0, tzinfo=tz), 2, 30, 0
)
assert datetime(2021, 11, 7, 2, 30, 0, tzinfo=tz, fold=1) == find(
datetime(2021, 11, 7, 2, 10, 0, tzinfo=tz), 2, 30, 0
)
assert datetime(2021, 11, 7, 2, 30, 0, tzinfo=tz, fold=1) == find(
datetime(2021, 11, 7, 2, 30, 0, tzinfo=tz, fold=0), 2, 30, 0
)
assert datetime(2021, 11, 8, 2, 30, 0, tzinfo=tz, fold=1) == find(
datetime(2021, 11, 7, 2, 55, 0, tzinfo=tz, fold=0), 2, 30, 0
)
assert datetime(2021, 11, 7, 4, 30, 0, tzinfo=tz, fold=0) == find(
datetime(2021, 11, 7, 2, 55, 0, tzinfo=tz, fold=1), 4, 30, 0
)
assert datetime(2021, 11, 7, 2, 30, 0, tzinfo=tz, fold=1) == find(
datetime(2021, 11, 7, 2, 5, 0, tzinfo=tz, fold=1), 2, 30, 0
)
assert datetime(2021, 11, 8, 2, 30, 0, tzinfo=tz) == find(
datetime(2021, 11, 7, 2, 55, 0, tzinfo=tz, fold=0), 2, 30, 0
)