diff --git a/homeassistant/components/moon/sensor.py b/homeassistant/components/moon/sensor.py index 4b373469cc6df9..6213e218d24d0d 100644 --- a/homeassistant/components/moon/sensor.py +++ b/homeassistant/components/moon/sensor.py @@ -1,5 +1,5 @@ """Support for tracking the moon phases.""" -from astral import Astral +from astral import moon import voluptuous as vol from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity @@ -48,7 +48,6 @@ def __init__(self, name): """Initialize the moon sensor.""" self._name = name self._state = None - self._astral = Astral() @property def name(self): @@ -87,4 +86,4 @@ def icon(self): async def async_update(self): """Get the time and updates the states.""" today = dt_util.as_local(dt_util.utcnow()).date() - self._state = self._astral.moon_phase(today) + self._state = moon.phase(today) diff --git a/homeassistant/components/sun/__init__.py b/homeassistant/components/sun/__init__.py index dfe3b15c110a01..489eab6b5be190 100644 --- a/homeassistant/components/sun/__init__.py +++ b/homeassistant/components/sun/__init__.py @@ -92,6 +92,7 @@ def __init__(self, hass): """Initialize the sun.""" self.hass = hass self.location = None + self.elevation = 0.0 self._state = self.next_rising = self.next_setting = None self.next_dawn = self.next_dusk = None self.next_midnight = self.next_noon = None @@ -100,10 +101,11 @@ def __init__(self, hass): self._next_change = None def update_location(_event): - location = get_astral_location(self.hass) + location, elevation = get_astral_location(self.hass) if location == self.location: return self.location = location + self.elevation = elevation self.update_events() update_location(None) @@ -140,7 +142,7 @@ def extra_state_attributes(self): def _check_event(self, utc_point_in_time, sun_event, before): next_utc = get_location_astral_event_next( - self.location, sun_event, utc_point_in_time + self.location, self.elevation, sun_event, utc_point_in_time ) if next_utc < self._next_change: self._next_change = next_utc @@ -169,7 +171,7 @@ def update_events(self, now=None): ) self.location.solar_depression = -10 self._check_event(utc_point_in_time, "dawn", PHASE_SMALL_DAY) - self.next_noon = self._check_event(utc_point_in_time, "solar_noon", None) + self.next_noon = self._check_event(utc_point_in_time, "noon", None) self._check_event(utc_point_in_time, "dusk", PHASE_DAY) self.next_setting = self._check_event( utc_point_in_time, SUN_EVENT_SUNSET, PHASE_SMALL_DAY @@ -180,9 +182,7 @@ def update_events(self, now=None): self._check_event(utc_point_in_time, "dusk", PHASE_NAUTICAL_TWILIGHT) self.location.solar_depression = "astronomical" self._check_event(utc_point_in_time, "dusk", PHASE_ASTRONOMICAL_TWILIGHT) - self.next_midnight = self._check_event( - utc_point_in_time, "solar_midnight", None - ) + self.next_midnight = self._check_event(utc_point_in_time, "midnight", None) self.location.solar_depression = "civil" # if the event was solar midday or midnight, phase will now @@ -190,7 +190,7 @@ def update_events(self, now=None): # even in the day at the poles, so we can't rely on it. # Need to calculate phase if next is noon or midnight if self.phase is None: - elevation = self.location.solar_elevation(self._next_change) + elevation = self.location.solar_elevation(self._next_change, self.elevation) if elevation >= 10: self.phase = PHASE_DAY elif elevation >= 0: @@ -222,9 +222,11 @@ def update_sun_position(self, now=None): """Calculate the position of the sun.""" # Grab current time in case system clock changed since last time we ran. utc_point_in_time = dt_util.utcnow() - self.solar_azimuth = round(self.location.solar_azimuth(utc_point_in_time), 2) + self.solar_azimuth = round( + self.location.solar_azimuth(utc_point_in_time, self.elevation), 2 + ) self.solar_elevation = round( - self.location.solar_elevation(utc_point_in_time), 2 + self.location.solar_elevation(utc_point_in_time, self.elevation), 2 ) _LOGGER.debug( diff --git a/homeassistant/components/tod/binary_sensor.py b/homeassistant/components/tod/binary_sensor.py index 26e0ead680a01e..a0fed1f803218b 100644 --- a/homeassistant/components/tod/binary_sensor.py +++ b/homeassistant/components/tod/binary_sensor.py @@ -173,20 +173,6 @@ def _calculate_initial_boudary_time(self): self._time_before = before_event_date - # We are calculating the _time_after value assuming that it will happen today - # But that is not always true, e.g. after 23:00, before 12:00 and now is 10:00 - # If _time_before and _time_after are ahead of current_datetime: - # _time_before is set to 12:00 next day - # _time_after is set to 23:00 today - # current_datetime is set to 10:00 today - if ( - self._time_after > self.current_datetime - and self._time_before > self.current_datetime + timedelta(days=1) - ): - # remove one day from _time_before and _time_after - self._time_after -= timedelta(days=1) - self._time_before -= timedelta(days=1) - # Add offset to utc boundaries according to the configuration self._time_after += self._after_offset self._time_before += self._before_offset diff --git a/homeassistant/helpers/sun.py b/homeassistant/helpers/sun.py index b3a37d238f9cdf..3c18dcc32784a5 100644 --- a/homeassistant/helpers/sun.py +++ b/homeassistant/helpers/sun.py @@ -14,27 +14,32 @@ DATA_LOCATION_CACHE = "astral_location_cache" +ELEVATION_AGNOSTIC_EVENTS = ("noon", "midnight") + @callback @bind_hass -def get_astral_location(hass: HomeAssistant) -> astral.Location: +def get_astral_location( + hass: HomeAssistant, +) -> tuple[astral.location.Location, astral.Elevation]: """Get an astral location for the current Home Assistant configuration.""" - from astral import Location # pylint: disable=import-outside-toplevel + from astral import LocationInfo # pylint: disable=import-outside-toplevel + from astral.location import Location # pylint: disable=import-outside-toplevel latitude = hass.config.latitude longitude = hass.config.longitude timezone = str(hass.config.time_zone) elevation = hass.config.elevation - info = ("", "", latitude, longitude, timezone, elevation) + info = ("", "", timezone, latitude, longitude) # Cache astral locations so they aren't recreated with the same args if DATA_LOCATION_CACHE not in hass.data: hass.data[DATA_LOCATION_CACHE] = {} if info not in hass.data[DATA_LOCATION_CACHE]: - hass.data[DATA_LOCATION_CACHE][info] = Location(info) + hass.data[DATA_LOCATION_CACHE][info] = Location(LocationInfo(*info)) - return hass.data[DATA_LOCATION_CACHE][info] + return hass.data[DATA_LOCATION_CACHE][info], elevation @callback @@ -46,19 +51,21 @@ def get_astral_event_next( offset: datetime.timedelta | None = None, ) -> datetime.datetime: """Calculate the next specified solar event.""" - location = get_astral_location(hass) - return get_location_astral_event_next(location, event, utc_point_in_time, offset) + location, elevation = get_astral_location(hass) + return get_location_astral_event_next( + location, elevation, event, utc_point_in_time, offset + ) @callback def get_location_astral_event_next( - location: astral.Location, + location: astral.location.Location, + elevation: astral.Elevation, event: str, utc_point_in_time: datetime.datetime | None = None, offset: datetime.timedelta | None = None, ) -> datetime.datetime: """Calculate the next specified solar event.""" - from astral import AstralError # pylint: disable=import-outside-toplevel if offset is None: offset = datetime.timedelta() @@ -66,6 +73,10 @@ def get_location_astral_event_next( if utc_point_in_time is None: utc_point_in_time = dt_util.utcnow() + kwargs = {"local": False} + if event not in ELEVATION_AGNOSTIC_EVENTS: + kwargs["observer_elevation"] = elevation + mod = -1 while True: try: @@ -73,13 +84,13 @@ def get_location_astral_event_next( getattr(location, event)( dt_util.as_local(utc_point_in_time).date() + datetime.timedelta(days=mod), - local=False, + **kwargs, ) + offset ) if next_dt > utc_point_in_time: return next_dt - except AstralError: + except ValueError: pass mod += 1 @@ -92,9 +103,7 @@ def get_astral_event_date( date: datetime.date | datetime.datetime | None = None, ) -> datetime.datetime | None: """Calculate the astral event time for the specified date.""" - from astral import AstralError # pylint: disable=import-outside-toplevel - - location = get_astral_location(hass) + location, elevation = get_astral_location(hass) if date is None: date = dt_util.now().date() @@ -102,9 +111,13 @@ def get_astral_event_date( if isinstance(date, datetime.datetime): date = dt_util.as_local(date).date() + kwargs = {"local": False} + if event not in ELEVATION_AGNOSTIC_EVENTS: + kwargs["observer_elevation"] = elevation + try: - return getattr(location, event)(date, local=False) # type: ignore - except AstralError: + return getattr(location, event)(date, **kwargs) # type: ignore + except ValueError: # Event never occurs for specified date. return None diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index edb1b2c9cc7f4c..a58a800287a734 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -3,7 +3,7 @@ PyNaCl==1.3.0 aiodiscover==1.3.2 aiohttp==3.7.4.post0 aiohttp_cors==0.7.0 -astral==1.10.1 +astral==2.2 async-upnp-client==0.16.0 async_timeout==3.0.1 attrs==20.3.0 diff --git a/requirements.txt b/requirements.txt index 5f633eaeb6910f..a3facbe5ab23f6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Home Assistant Core aiohttp==3.7.4.post0 -astral==1.10.1 +astral==2.2 async_timeout==3.0.1 attrs==20.3.0 awesomeversion==21.2.3 diff --git a/setup.py b/setup.py index 56e56391489f97..f74a913cb81ca7 100755 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ REQUIRES = [ "aiohttp==3.7.4.post0", - "astral==1.10.1", + "astral==2.2", "async_timeout==3.0.1", "attrs==20.3.0", "awesomeversion==21.2.3", diff --git a/tests/components/sun/test_init.py b/tests/components/sun/test_init.py index 1e95082b3581b5..800d3ab82fd4fd 100644 --- a/tests/components/sun/test_init.py +++ b/tests/components/sun/test_init.py @@ -22,18 +22,19 @@ async def test_setting_rising(hass, legacy_patchable_time): await hass.async_block_till_done() state = hass.states.get(sun.ENTITY_ID) - from astral import Astral + from astral import LocationInfo + import astral.sun - astral = Astral() utc_today = utc_now.date() - latitude = hass.config.latitude - longitude = hass.config.longitude + location = LocationInfo( + latitude=hass.config.latitude, longitude=hass.config.longitude + ) mod = -1 while True: - next_dawn = astral.dawn_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_dawn = astral.sun.dawn( + location.observer, date=utc_today + timedelta(days=mod) ) if next_dawn > utc_now: break @@ -41,8 +42,8 @@ async def test_setting_rising(hass, legacy_patchable_time): mod = -1 while True: - next_dusk = astral.dusk_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_dusk = astral.sun.dusk( + location.observer, date=utc_today + timedelta(days=mod) ) if next_dusk > utc_now: break @@ -50,8 +51,8 @@ async def test_setting_rising(hass, legacy_patchable_time): mod = -1 while True: - next_midnight = astral.solar_midnight_utc( - utc_today + timedelta(days=mod), longitude + next_midnight = astral.sun.midnight( + location.observer, date=utc_today + timedelta(days=mod) ) if next_midnight > utc_now: break @@ -59,15 +60,17 @@ async def test_setting_rising(hass, legacy_patchable_time): mod = -1 while True: - next_noon = astral.solar_noon_utc(utc_today + timedelta(days=mod), longitude) + next_noon = astral.sun.noon( + location.observer, date=utc_today + timedelta(days=mod) + ) if next_noon > utc_now: break mod += 1 mod = -1 while True: - next_rising = astral.sunrise_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_rising = astral.sun.sunrise( + location.observer, date=utc_today + timedelta(days=mod) ) if next_rising > utc_now: break @@ -75,8 +78,8 @@ async def test_setting_rising(hass, legacy_patchable_time): mod = -1 while True: - next_setting = astral.sunset_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_setting = astral.sun.sunset( + location.observer, date=utc_today + timedelta(days=mod) ) if next_setting > utc_now: break @@ -152,10 +155,10 @@ async def test_norway_in_june(hass): assert dt_util.parse_datetime( state.attributes[sun.STATE_ATTR_NEXT_RISING] - ) == datetime(2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC) + ) == datetime(2016, 7, 24, 22, 59, 45, 689645, tzinfo=dt_util.UTC) assert dt_util.parse_datetime( state.attributes[sun.STATE_ATTR_NEXT_SETTING] - ) == datetime(2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC) + ) == datetime(2016, 7, 25, 22, 17, 13, 503932, tzinfo=dt_util.UTC) assert state.state == sun.STATE_ABOVE_HORIZON diff --git a/tests/components/sun/test_trigger.py b/tests/components/sun/test_trigger.py index 3ed91d1d896de4..54dcef96e28e07 100644 --- a/tests/components/sun/test_trigger.py +++ b/tests/components/sun/test_trigger.py @@ -188,17 +188,17 @@ async def test_if_action_before_sunrise_no_offset(hass, calls): }, ) - # sunrise: 2015-09-16 06:32:43 local, sunset: 2015-09-16 18:55:24 local - # sunrise: 2015-09-16 13:32:43 UTC, sunset: 2015-09-17 01:55:24 UTC + # sunrise: 2015-09-16 06:33:18 local, sunset: 2015-09-16 18:53:45 local + # sunrise: 2015-09-16 13:33:18 UTC, sunset: 2015-09-17 01:53:45 UTC # now = sunrise + 1s -> 'before sunrise' not true - now = datetime(2015, 9, 16, 13, 32, 44, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 13, 33, 19, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 # now = sunrise -> 'before sunrise' true - now = datetime(2015, 9, 16, 13, 32, 43, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 13, 33, 18, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -237,17 +237,17 @@ async def test_if_action_after_sunrise_no_offset(hass, calls): }, ) - # sunrise: 2015-09-16 06:32:43 local, sunset: 2015-09-16 18:55:24 local - # sunrise: 2015-09-16 13:32:43 UTC, sunset: 2015-09-17 01:55:24 UTC + # sunrise: 2015-09-16 06:33:18 local, sunset: 2015-09-16 18:53:45 local + # sunrise: 2015-09-16 13:33:18 UTC, sunset: 2015-09-17 01:53:45 UTC # now = sunrise - 1s -> 'after sunrise' not true - now = datetime(2015, 9, 16, 13, 32, 42, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 13, 33, 17, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 # now = sunrise + 1s -> 'after sunrise' true - now = datetime(2015, 9, 16, 13, 32, 43, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 13, 33, 19, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -290,17 +290,17 @@ async def test_if_action_before_sunrise_with_offset(hass, calls): }, ) - # sunrise: 2015-09-16 06:32:43 local, sunset: 2015-09-16 18:55:24 local - # sunrise: 2015-09-16 13:32:43 UTC, sunset: 2015-09-17 01:55:24 UTC + # sunrise: 2015-09-16 06:33:18 local, sunset: 2015-09-16 18:53:45 local + # sunrise: 2015-09-16 13:33:18 UTC, sunset: 2015-09-17 01:53:45 UTC # now = sunrise + 1s + 1h -> 'before sunrise' with offset +1h not true - now = datetime(2015, 9, 16, 14, 32, 44, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 14, 33, 19, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 # now = sunrise + 1h -> 'before sunrise' with offset +1h true - now = datetime(2015, 9, 16, 14, 32, 43, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 14, 33, 18, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -335,14 +335,14 @@ async def test_if_action_before_sunrise_with_offset(hass, calls): assert len(calls) == 2 # now = sunset -> 'before sunrise' with offset +1h not true - now = datetime(2015, 9, 17, 1, 56, 48, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 1, 53, 45, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 2 # now = sunset -1s -> 'before sunrise' with offset +1h not true - now = datetime(2015, 9, 17, 1, 56, 45, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 1, 53, 44, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -371,8 +371,8 @@ async def test_if_action_before_sunset_with_offset(hass, calls): }, ) - # sunrise: 2015-09-16 06:32:43 local, sunset: 2015-09-16 18:55:24 local - # sunrise: 2015-09-16 13:32:43 UTC, sunset: 2015-09-17 01:55:24 UTC + # sunrise: 2015-09-16 06:33:18 local, sunset: 2015-09-16 18:53:45 local + # sunrise: 2015-09-16 13:33:18 UTC, sunset: 2015-09-17 01:53:45 UTC # now = local midnight -> 'before sunset' with offset +1h true now = datetime(2015, 9, 16, 7, 0, 0, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): @@ -381,14 +381,14 @@ async def test_if_action_before_sunset_with_offset(hass, calls): assert len(calls) == 1 # now = sunset + 1s + 1h -> 'before sunset' with offset +1h not true - now = datetime(2015, 9, 17, 2, 55, 25, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 2, 53, 46, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 1 # now = sunset + 1h -> 'before sunset' with offset +1h true - now = datetime(2015, 9, 17, 2, 55, 24, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 2, 53, 44, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -409,14 +409,14 @@ async def test_if_action_before_sunset_with_offset(hass, calls): assert len(calls) == 4 # now = sunrise -> 'before sunset' with offset +1h true - now = datetime(2015, 9, 16, 13, 32, 43, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 13, 33, 18, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 5 # now = sunrise -1s -> 'before sunset' with offset +1h true - now = datetime(2015, 9, 16, 13, 32, 42, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 13, 33, 17, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -452,17 +452,17 @@ async def test_if_action_after_sunrise_with_offset(hass, calls): }, ) - # sunrise: 2015-09-16 06:32:43 local, sunset: 2015-09-16 18:55:24 local - # sunrise: 2015-09-16 13:32:43 UTC, sunset: 2015-09-17 01:55:24 UTC + # sunrise: 2015-09-16 06:33:18 local, sunset: 2015-09-16 18:53:45 local + # sunrise: 2015-09-16 13:33:18 UTC, sunset: 2015-09-17 01:53:45 UTC # now = sunrise - 1s + 1h -> 'after sunrise' with offset +1h not true - now = datetime(2015, 9, 16, 14, 32, 42, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 14, 33, 17, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 # now = sunrise + 1h -> 'after sunrise' with offset +1h true - now = datetime(2015, 9, 16, 14, 32, 43, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 14, 33, 58, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -497,14 +497,14 @@ async def test_if_action_after_sunrise_with_offset(hass, calls): assert len(calls) == 3 # now = sunset -> 'after sunrise' with offset +1h true - now = datetime(2015, 9, 17, 1, 55, 24, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 1, 53, 45, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 4 # now = sunset + 1s -> 'after sunrise' with offset +1h true - now = datetime(2015, 9, 17, 1, 55, 25, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 1, 53, 45, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -547,17 +547,17 @@ async def test_if_action_after_sunset_with_offset(hass, calls): }, ) - # sunrise: 2015-09-15 06:32:05 local, sunset: 2015-09-15 18:56:46 local - # sunrise: 2015-09-15 13:32:05 UTC, sunset: 2015-09-16 01:56:46 UTC + # sunrise: 2015-09-16 06:33:18 local, sunset: 2015-09-16 18:53:45 local + # sunrise: 2015-09-16 13:33:18 UTC, sunset: 2015-09-17 01:53:45 UTC # now = sunset - 1s + 1h -> 'after sunset' with offset +1h not true - now = datetime(2015, 9, 16, 2, 56, 45, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 2, 53, 44, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 # now = sunset + 1h -> 'after sunset' with offset +1h true - now = datetime(2015, 9, 16, 2, 56, 46, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 2, 53, 45, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -600,31 +600,31 @@ async def test_if_action_before_and_after_during(hass, calls): }, ) - # sunrise: 2015-09-16 06:32:43 local, sunset: 2015-09-16 18:55:24 local - # sunrise: 2015-09-16 13:32:43 UTC, sunset: 2015-09-17 01:55:24 UTC + # sunrise: 2015-09-16 06:33:18 local, sunset: 2015-09-16 18:53:45 local + # sunrise: 2015-09-16 13:33:18 UTC, sunset: 2015-09-17 01:53:45 UTC # now = sunrise - 1s -> 'after sunrise' + 'before sunset' not true - now = datetime(2015, 9, 16, 13, 32, 42, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 16, 13, 33, 17, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 # now = sunset + 1s -> 'after sunrise' + 'before sunset' not true - now = datetime(2015, 9, 17, 1, 55, 25, tzinfo=dt_util.UTC) + now = datetime(2015, 9, 17, 1, 53, 46, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 - # now = sunrise -> 'after sunrise' + 'before sunset' true - now = datetime(2015, 9, 16, 13, 32, 43, tzinfo=dt_util.UTC) + # now = sunrise + 1s -> 'after sunrise' + 'before sunset' true + now = datetime(2015, 9, 16, 13, 33, 19, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 1 - # now = sunset -> 'after sunrise' + 'before sunset' true - now = datetime(2015, 9, 17, 1, 55, 24, tzinfo=dt_util.UTC) + # now = sunset - 1s -> 'after sunrise' + 'before sunset' true + now = datetime(2015, 9, 17, 1, 53, 44, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -663,17 +663,17 @@ async def test_if_action_before_sunrise_no_offset_kotzebue(hass, calls): }, ) - # sunrise: 2015-07-24 07:17:24 local, sunset: 2015-07-25 03:16:27 local - # sunrise: 2015-07-24 15:17:24 UTC, sunset: 2015-07-25 11:16:27 UTC + # sunrise: 2015-07-24 07:21:12 local, sunset: 2015-07-25 03:13:33 local + # sunrise: 2015-07-24 15:21:12 UTC, sunset: 2015-07-25 11:13:33 UTC # now = sunrise + 1s -> 'before sunrise' not true - now = datetime(2015, 7, 24, 15, 17, 25, tzinfo=dt_util.UTC) + now = datetime(2015, 7, 24, 15, 21, 13, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 - # now = sunrise -> 'before sunrise' true - now = datetime(2015, 7, 24, 15, 17, 24, tzinfo=dt_util.UTC) + # now = sunrise - 1h -> 'before sunrise' true + now = datetime(2015, 7, 24, 14, 21, 12, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -719,17 +719,17 @@ async def test_if_action_after_sunrise_no_offset_kotzebue(hass, calls): }, ) - # sunrise: 2015-07-24 07:17:24 local, sunset: 2015-07-25 03:16:27 local - # sunrise: 2015-07-24 15:17:24 UTC, sunset: 2015-07-25 11:16:27 UTC + # sunrise: 2015-07-24 07:21:12 local, sunset: 2015-07-25 03:13:33 local + # sunrise: 2015-07-24 15:21:12 UTC, sunset: 2015-07-25 11:13:33 UTC # now = sunrise -> 'after sunrise' true - now = datetime(2015, 7, 24, 15, 17, 24, tzinfo=dt_util.UTC) + now = datetime(2015, 7, 24, 15, 21, 12, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 1 - # now = sunrise - 1s -> 'after sunrise' not true - now = datetime(2015, 7, 24, 15, 17, 23, tzinfo=dt_util.UTC) + # now = sunrise - 1h -> 'after sunrise' not true + now = datetime(2015, 7, 24, 14, 21, 12, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -775,17 +775,17 @@ async def test_if_action_before_sunset_no_offset_kotzebue(hass, calls): }, ) - # sunrise: 2015-07-24 07:17:24 local, sunset: 2015-07-25 03:16:27 local - # sunrise: 2015-07-24 15:17:24 UTC, sunset: 2015-07-25 11:16:27 UTC - # now = sunrise + 1s -> 'before sunrise' not true - now = datetime(2015, 7, 25, 11, 16, 28, tzinfo=dt_util.UTC) + # sunrise: 2015-07-24 07:21:12 local, sunset: 2015-07-25 03:13:33 local + # sunrise: 2015-07-24 15:21:12 UTC, sunset: 2015-07-25 11:13:33 UTC + # now = sunset + 1s -> 'before sunset' not true + now = datetime(2015, 7, 25, 11, 13, 34, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 0 - # now = sunrise -> 'before sunrise' true - now = datetime(2015, 7, 25, 11, 16, 27, tzinfo=dt_util.UTC) + # now = sunset - 1h-> 'before sunset' true + now = datetime(2015, 7, 25, 10, 13, 33, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() @@ -831,17 +831,17 @@ async def test_if_action_after_sunset_no_offset_kotzebue(hass, calls): }, ) - # sunrise: 2015-07-24 07:17:24 local, sunset: 2015-07-25 03:16:27 local - # sunrise: 2015-07-24 15:17:24 UTC, sunset: 2015-07-25 11:16:27 UTC + # sunrise: 2015-07-24 07:21:12 local, sunset: 2015-07-25 03:13:33 local + # sunrise: 2015-07-24 15:21:12 UTC, sunset: 2015-07-25 11:13:33 UTC # now = sunset -> 'after sunset' true - now = datetime(2015, 7, 25, 11, 16, 27, tzinfo=dt_util.UTC) + now = datetime(2015, 7, 25, 11, 13, 33, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() assert len(calls) == 1 # now = sunset - 1s -> 'after sunset' not true - now = datetime(2015, 7, 25, 11, 16, 26, tzinfo=dt_util.UTC) + now = datetime(2015, 7, 25, 11, 13, 32, tzinfo=dt_util.UTC) with patch("homeassistant.util.dt.utcnow", return_value=now): hass.bus.async_fire("test_event") await hass.async_block_till_done() diff --git a/tests/components/tod/test_binary_sensor.py b/tests/components/tod/test_binary_sensor.py index 363d159b811c67..2eb506f80f362b 100644 --- a/tests/components/tod/test_binary_sensor.py +++ b/tests/components/tod/test_binary_sensor.py @@ -643,6 +643,7 @@ async def test_norwegian_case_summer(hass): """Test location in Norway where the sun doesn't set in summer.""" hass.config.latitude = 69.6 hass.config.longitude = 18.8 + hass.config.elevation = 10.0 test_time = hass.config.time_zone.localize(datetime(2010, 6, 1)).astimezone( pytz.UTC @@ -652,7 +653,7 @@ async def test_norwegian_case_summer(hass): get_astral_event_next(hass, "sunrise", dt_util.as_utc(test_time)) ) sunset = dt_util.as_local( - get_astral_event_next(hass, "sunset", dt_util.as_utc(test_time)) + get_astral_event_next(hass, "sunset", dt_util.as_utc(sunrise)) ) config = { "binary_sensor": [ diff --git a/tests/helpers/test_event.py b/tests/helpers/test_event.py index b0f58f76a661ae..b8291b97efa888 100644 --- a/tests/helpers/test_event.py +++ b/tests/helpers/test_event.py @@ -4,7 +4,8 @@ from datetime import datetime, timedelta from unittest.mock import patch -from astral import Astral +from astral import LocationInfo +import astral.sun import jinja2 import pytest @@ -2433,15 +2434,18 @@ async def test_track_sunrise(hass, legacy_patchable_time): hass, sun.DOMAIN, {sun.DOMAIN: {sun.CONF_ELEVATION: 0}} ) + location = LocationInfo( + latitude=hass.config.latitude, longitude=hass.config.longitude + ) + # Get next sunrise/sunset - astral = Astral() utc_now = datetime(2014, 5, 24, 12, 0, 0, tzinfo=dt_util.UTC) utc_today = utc_now.date() mod = -1 while True: - next_rising = astral.sunrise_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_rising = astral.sun.sunrise( + location.observer, date=utc_today + timedelta(days=mod) ) if next_rising > utc_now: break @@ -2493,15 +2497,18 @@ async def test_track_sunrise_update_location(hass, legacy_patchable_time): hass, sun.DOMAIN, {sun.DOMAIN: {sun.CONF_ELEVATION: 0}} ) + location = LocationInfo( + latitude=hass.config.latitude, longitude=hass.config.longitude + ) + # Get next sunrise - astral = Astral() utc_now = datetime(2014, 5, 24, 12, 0, 0, tzinfo=dt_util.UTC) utc_today = utc_now.date() mod = -1 while True: - next_rising = astral.sunrise_utc( - utc_today + timedelta(days=mod), hass.config.latitude, hass.config.longitude + next_rising = astral.sun.sunrise( + location.observer, date=utc_today + timedelta(days=mod) ) if next_rising > utc_now: break @@ -2522,6 +2529,11 @@ async def test_track_sunrise_update_location(hass, legacy_patchable_time): await hass.config.async_update(latitude=40.755931, longitude=-73.984606) await hass.async_block_till_done() + # update location for astral + location = LocationInfo( + latitude=hass.config.latitude, longitude=hass.config.longitude + ) + # Mimic sunrise async_fire_time_changed(hass, next_rising) await hass.async_block_till_done() @@ -2531,8 +2543,8 @@ async def test_track_sunrise_update_location(hass, legacy_patchable_time): # Get next sunrise mod = -1 while True: - next_rising = astral.sunrise_utc( - utc_today + timedelta(days=mod), hass.config.latitude, hass.config.longitude + next_rising = astral.sun.sunrise( + location.observer, date=utc_today + timedelta(days=mod) ) if next_rising > utc_now: break @@ -2549,6 +2561,8 @@ async def test_track_sunset(hass, legacy_patchable_time): latitude = 32.87336 longitude = 117.22743 + location = LocationInfo(latitude=latitude, longitude=longitude) + # Setup sun component hass.config.latitude = latitude hass.config.longitude = longitude @@ -2557,14 +2571,13 @@ async def test_track_sunset(hass, legacy_patchable_time): ) # Get next sunrise/sunset - astral = Astral() utc_now = datetime(2014, 5, 24, 12, 0, 0, tzinfo=dt_util.UTC) utc_today = utc_now.date() mod = -1 while True: - next_setting = astral.sunset_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_setting = astral.sun.sunset( + location.observer, date=utc_today + timedelta(days=mod) ) if next_setting > utc_now: break diff --git a/tests/helpers/test_sun.py b/tests/helpers/test_sun.py index b8ecd1ed86aa96..84545bf43b60a0 100644 --- a/tests/helpers/test_sun.py +++ b/tests/helpers/test_sun.py @@ -11,18 +11,19 @@ def test_next_events(hass): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) - from astral import Astral + from astral import LocationInfo + import astral.sun - astral = Astral() utc_today = utc_now.date() - latitude = hass.config.latitude - longitude = hass.config.longitude + location = LocationInfo( + latitude=hass.config.latitude, longitude=hass.config.longitude + ) mod = -1 while True: - next_dawn = astral.dawn_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_dawn = astral.sun.dawn( + location.observer, date=utc_today + timedelta(days=mod) ) if next_dawn > utc_now: break @@ -30,8 +31,8 @@ def test_next_events(hass): mod = -1 while True: - next_dusk = astral.dusk_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_dusk = astral.sun.dusk( + location.observer, date=utc_today + timedelta(days=mod) ) if next_dusk > utc_now: break @@ -39,8 +40,8 @@ def test_next_events(hass): mod = -1 while True: - next_midnight = astral.solar_midnight_utc( - utc_today + timedelta(days=mod), longitude + next_midnight = astral.sun.midnight( + location.observer, date=utc_today + timedelta(days=mod) ) if next_midnight > utc_now: break @@ -48,15 +49,17 @@ def test_next_events(hass): mod = -1 while True: - next_noon = astral.solar_noon_utc(utc_today + timedelta(days=mod), longitude) + next_noon = astral.sun.noon( + location.observer, date=utc_today + timedelta(days=mod) + ) if next_noon > utc_now: break mod += 1 mod = -1 while True: - next_rising = astral.sunrise_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_rising = astral.sun.sunrise( + location.observer, date=utc_today + timedelta(days=mod) ) if next_rising > utc_now: break @@ -64,8 +67,8 @@ def test_next_events(hass): mod = -1 while True: - next_setting = astral.sunset_utc( - utc_today + timedelta(days=mod), latitude, longitude + next_setting = astral.sun.sunset( + location.observer, utc_today + timedelta(days=mod) ) if next_setting > utc_now: break @@ -74,8 +77,8 @@ def test_next_events(hass): with patch("homeassistant.helpers.condition.dt_util.utcnow", return_value=utc_now): assert next_dawn == sun.get_astral_event_next(hass, "dawn") assert next_dusk == sun.get_astral_event_next(hass, "dusk") - assert next_midnight == sun.get_astral_event_next(hass, "solar_midnight") - assert next_noon == sun.get_astral_event_next(hass, "solar_noon") + assert next_midnight == sun.get_astral_event_next(hass, "midnight") + assert next_noon == sun.get_astral_event_next(hass, "noon") assert next_rising == sun.get_astral_event_next(hass, SUN_EVENT_SUNRISE) assert next_setting == sun.get_astral_event_next(hass, SUN_EVENT_SUNSET) @@ -83,25 +86,26 @@ def test_next_events(hass): def test_date_events(hass): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) - from astral import Astral + from astral import LocationInfo + import astral.sun - astral = Astral() utc_today = utc_now.date() - latitude = hass.config.latitude - longitude = hass.config.longitude + location = LocationInfo( + latitude=hass.config.latitude, longitude=hass.config.longitude + ) - dawn = astral.dawn_utc(utc_today, latitude, longitude) - dusk = astral.dusk_utc(utc_today, latitude, longitude) - midnight = astral.solar_midnight_utc(utc_today, longitude) - noon = astral.solar_noon_utc(utc_today, longitude) - sunrise = astral.sunrise_utc(utc_today, latitude, longitude) - sunset = astral.sunset_utc(utc_today, latitude, longitude) + dawn = astral.sun.dawn(location.observer, utc_today) + dusk = astral.sun.dusk(location.observer, utc_today) + midnight = astral.sun.midnight(location.observer, utc_today) + noon = astral.sun.noon(location.observer, utc_today) + sunrise = astral.sun.sunrise(location.observer, utc_today) + sunset = astral.sun.sunset(location.observer, utc_today) assert dawn == sun.get_astral_event_date(hass, "dawn", utc_today) assert dusk == sun.get_astral_event_date(hass, "dusk", utc_today) - assert midnight == sun.get_astral_event_date(hass, "solar_midnight", utc_today) - assert noon == sun.get_astral_event_date(hass, "solar_noon", utc_today) + assert midnight == sun.get_astral_event_date(hass, "midnight", utc_today) + assert noon == sun.get_astral_event_date(hass, "noon", utc_today) assert sunrise == sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, utc_today) assert sunset == sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, utc_today) @@ -109,26 +113,27 @@ def test_date_events(hass): def test_date_events_default_date(hass): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) - from astral import Astral + from astral import LocationInfo + import astral.sun - astral = Astral() utc_today = utc_now.date() - latitude = hass.config.latitude - longitude = hass.config.longitude + location = LocationInfo( + latitude=hass.config.latitude, longitude=hass.config.longitude + ) - dawn = astral.dawn_utc(utc_today, latitude, longitude) - dusk = astral.dusk_utc(utc_today, latitude, longitude) - midnight = astral.solar_midnight_utc(utc_today, longitude) - noon = astral.solar_noon_utc(utc_today, longitude) - sunrise = astral.sunrise_utc(utc_today, latitude, longitude) - sunset = astral.sunset_utc(utc_today, latitude, longitude) + dawn = astral.sun.dawn(location.observer, date=utc_today) + dusk = astral.sun.dusk(location.observer, date=utc_today) + midnight = astral.sun.midnight(location.observer, date=utc_today) + noon = astral.sun.noon(location.observer, date=utc_today) + sunrise = astral.sun.sunrise(location.observer, date=utc_today) + sunset = astral.sun.sunset(location.observer, date=utc_today) with patch("homeassistant.util.dt.now", return_value=utc_now): assert dawn == sun.get_astral_event_date(hass, "dawn", utc_today) assert dusk == sun.get_astral_event_date(hass, "dusk", utc_today) - assert midnight == sun.get_astral_event_date(hass, "solar_midnight", utc_today) - assert noon == sun.get_astral_event_date(hass, "solar_noon", utc_today) + assert midnight == sun.get_astral_event_date(hass, "midnight", utc_today) + assert noon == sun.get_astral_event_date(hass, "noon", utc_today) assert sunrise == sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, utc_today) assert sunset == sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, utc_today) @@ -136,25 +141,26 @@ def test_date_events_default_date(hass): def test_date_events_accepts_datetime(hass): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) - from astral import Astral + from astral import LocationInfo + import astral.sun - astral = Astral() utc_today = utc_now.date() - latitude = hass.config.latitude - longitude = hass.config.longitude + location = LocationInfo( + latitude=hass.config.latitude, longitude=hass.config.longitude + ) - dawn = astral.dawn_utc(utc_today, latitude, longitude) - dusk = astral.dusk_utc(utc_today, latitude, longitude) - midnight = astral.solar_midnight_utc(utc_today, longitude) - noon = astral.solar_noon_utc(utc_today, longitude) - sunrise = astral.sunrise_utc(utc_today, latitude, longitude) - sunset = astral.sunset_utc(utc_today, latitude, longitude) + dawn = astral.sun.dawn(location.observer, date=utc_today) + dusk = astral.sun.dusk(location.observer, date=utc_today) + midnight = astral.sun.midnight(location.observer, date=utc_today) + noon = astral.sun.noon(location.observer, date=utc_today) + sunrise = astral.sun.sunrise(location.observer, date=utc_today) + sunset = astral.sun.sunset(location.observer, date=utc_today) assert dawn == sun.get_astral_event_date(hass, "dawn", utc_now) assert dusk == sun.get_astral_event_date(hass, "dusk", utc_now) - assert midnight == sun.get_astral_event_date(hass, "solar_midnight", utc_now) - assert noon == sun.get_astral_event_date(hass, "solar_noon", utc_now) + assert midnight == sun.get_astral_event_date(hass, "midnight", utc_now) + assert noon == sun.get_astral_event_date(hass, "noon", utc_now) assert sunrise == sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, utc_now) assert sunset == sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, utc_now) @@ -184,10 +190,10 @@ def test_norway_in_june(hass): print(sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, datetime(2017, 7, 26))) assert sun.get_astral_event_next(hass, SUN_EVENT_SUNRISE, june) == datetime( - 2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC + 2016, 7, 24, 22, 59, 45, 689645, tzinfo=dt_util.UTC ) assert sun.get_astral_event_next(hass, SUN_EVENT_SUNSET, june) == datetime( - 2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC + 2016, 7, 25, 22, 17, 13, 503932, tzinfo=dt_util.UTC ) assert sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, june) is None assert sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, june) is None