Update calendar to always request start/end dates in local time rather than UTC (#90386)

This commit is contained in:
Allen Porter 2023-03-28 03:25:44 -07:00 committed by GitHub
parent be5714e3fd
commit ae41547b73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 13 deletions

View file

@ -523,7 +523,7 @@ class CalendarEventView(http.HomeAssistantView):
try: try:
calendar_event_list = await entity.async_get_events( calendar_event_list = await entity.async_get_events(
request.app["hass"], start_date, end_date request.app["hass"], dt.as_local(start_date), dt.as_local(end_date)
) )
except HomeAssistantError as err: except HomeAssistantError as err:
_LOGGER.debug("Error reading events: %s", err) _LOGGER.debug("Error reading events: %s", err)

View file

@ -283,8 +283,8 @@ class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
"Unable to get events: Sync from server has not completed" "Unable to get events: Sync from server has not completed"
) )
return self.data.overlapping( return self.data.overlapping(
dt_util.as_local(start_date), start_date,
dt_util.as_local(end_date), end_date,
) )
@property @property

View file

@ -85,17 +85,16 @@ class LocalCalendarEntity(CalendarEntity):
self, hass: HomeAssistant, start_date: datetime, end_date: datetime self, hass: HomeAssistant, start_date: datetime, end_date: datetime
) -> list[CalendarEvent]: ) -> list[CalendarEvent]:
"""Get all events in a specific time frame.""" """Get all events in a specific time frame."""
events = self._calendar.timeline_tz(dt_util.DEFAULT_TIME_ZONE).overlapping( events = self._calendar.timeline_tz(start_date.tzinfo).overlapping(
dt_util.as_local(start_date), start_date,
dt_util.as_local(end_date), end_date,
) )
return [_get_calendar_event(event) for event in events] return [_get_calendar_event(event) for event in events]
async def async_update(self) -> None: async def async_update(self) -> None:
"""Update entity state with the next upcoming event.""" """Update entity state with the next upcoming event."""
events = self._calendar.timeline_tz(dt_util.DEFAULT_TIME_ZONE).active_after( now = dt_util.now()
dt_util.now() events = self._calendar.timeline_tz(now.tzinfo).active_after(now)
)
if event := next(events, None): if event := next(events, None):
self._event = _get_calendar_event(event) self._event = _get_calendar_event(event)
else: else:

View file

@ -37,10 +37,27 @@ async def test_empty_calendar(
} }
@pytest.mark.parametrize(
("dtstart", "dtend"),
[
("1997-07-14T18:00:00+01:00", "1997-07-15T05:00:00+01:00"),
("1997-07-14T17:00:00+00:00", "1997-07-15T04:00:00+00:00"),
("1997-07-14T11:00:00-06:00", "1997-07-14T22:00:00-06:00"),
("1997-07-14T10:00:00-07:00", "1997-07-14T21:00:00-07:00"),
],
)
async def test_api_date_time_event( async def test_api_date_time_event(
ws_client: ClientFixture, setup_integration: None, get_events: GetEventsFn ws_client: ClientFixture,
setup_integration: None,
get_events: GetEventsFn,
dtstart: str,
dtend: str,
) -> None: ) -> None:
"""Test an event with a start/end date time.""" """Test an event with a start/end date time.
Events created in various timezones are ultimately returned relative
to local home assistant timezone.
"""
client = await ws_client() client = await ws_client()
await client.cmd_result( await client.cmd_result(
"create", "create",
@ -48,8 +65,8 @@ async def test_api_date_time_event(
"entity_id": TEST_ENTITY, "entity_id": TEST_ENTITY,
"event": { "event": {
"summary": "Bastille Day Party", "summary": "Bastille Day Party",
"dtstart": "1997-07-14T17:00:00+00:00", "dtstart": dtstart,
"dtend": "1997-07-15T04:00:00+00:00", "dtend": dtend,
}, },
}, },
) )
@ -63,6 +80,8 @@ async def test_api_date_time_event(
} }
] ]
# Query events in UTC
# Time range before event # Time range before event
events = await get_events("1997-07-13T00:00:00Z", "1997-07-14T16:00:00Z") events = await get_events("1997-07-13T00:00:00Z", "1997-07-14T16:00:00Z")
assert len(events) == 0 assert len(events) == 0
@ -77,6 +96,12 @@ async def test_api_date_time_event(
events = await get_events("1997-07-15T03:00:00Z", "1997-07-15T06:00:00Z") events = await get_events("1997-07-15T03:00:00Z", "1997-07-15T06:00:00Z")
assert len(events) == 1 assert len(events) == 1
# Query events overlapping with start and end but in another timezone
events = await get_events("1997-07-12T23:00:00-01:00", "1997-07-14T17:00:00-01:00")
assert len(events) == 1
events = await get_events("1997-07-15T02:00:00-01:00", "1997-07-15T05:00:00-01:00")
assert len(events) == 1
async def test_api_date_event( async def test_api_date_event(
ws_client: ClientFixture, setup_integration: None, get_events: GetEventsFn ws_client: ClientFixture, setup_integration: None, get_events: GetEventsFn