Fix #28104 - CalDav support for floating datetimes (#28123)

* Fix #28104 - CalDav support for floating datetimes

Timzones are optional in CalDav

It is possible that an entry contains neither a TZID, nor is an UTC time.
When this is the case, it should be treated as a floating date-time value,
which represent the same hour, minute, and second value regardless of which
time zone is currently being observed.

For Home-Assistant the correct timezone therefore is whatever is configured
as local time in the settings.

See https://www.kanzaki.com/docs/ical/dateTime.html

* Revert "Fix #28104 - CalDav support for floating datetimes"

This reverts commit cf32a6e39058e340816ae1e3ebd4a2c236b91964.

* add test case: floating events fail with error without patch

* Fix #28104 - CalDav support for floating datetimes

Timzones are optional in CalDav

It is possible that an entry contains neither a TZID, nor is an UTC time.
When this is the case, it should be treated as a floating date-time value,
which represent the same hour, minute, and second value regardless of which
time zone is currently being observed.

For Home-Assistant the correct timezone therefore is whatever is configured
as local time in the settings.

See https://www.kanzaki.com/docs/ical/dateTime.html

* style fix
This commit is contained in:
Lukas 2019-10-23 08:08:38 +02:00 committed by Paulus Schoutsen
parent 703cd96186
commit 65263bdef9
2 changed files with 40 additions and 0 deletions

View File

@ -278,6 +278,10 @@ class WebDavCalendarData:
def to_datetime(obj):
"""Return a datetime."""
if isinstance(obj, datetime):
if obj.tzinfo is None:
# floating value, not bound to any time zone in particular
# represent same time regardless of which time zone is currently being observed
return obj.replace(tzinfo=dt.DEFAULT_TIME_ZONE)
return obj
return dt.as_local(dt.dt.datetime.combine(obj, dt.dt.time.min))

View File

@ -111,6 +111,19 @@ LOCATION:San Francisco
DESCRIPTION:Sunny day
END:VEVENT
END:VCALENDAR
""",
"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Global Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:8
DTSTART:20171127T190000
DTEND:20171127T200000
SUMMARY:This is a floating Event
LOCATION:Hamburg
DESCRIPTION:What a day
END:VEVENT
END:VCALENDAR
""",
]
@ -292,6 +305,29 @@ async def test_ongoing_event_different_tz(mock_now, hass, calendar):
}
@patch("homeassistant.util.dt.now", return_value=_local_datetime(19, 10))
async def test_ongoing_floating_event_returned(mock_now, hass, calendar):
"""Test that floating events without timezones work."""
assert await async_setup_component(hass, "calendar", {"calendar": CALDAV_CONFIG})
await hass.async_block_till_done()
state = hass.states.get("calendar.private")
print(dt.DEFAULT_TIME_ZONE)
print(state)
assert state.name == calendar.name
assert state.state == STATE_ON
assert dict(state.attributes) == {
"friendly_name": "Private",
"message": "This is a floating Event",
"all_day": False,
"offset_reached": False,
"start_time": "2017-11-27 19:00:00",
"end_time": "2017-11-27 20:00:00",
"location": "Hamburg",
"description": "What a day",
}
@patch("homeassistant.util.dt.now", return_value=_local_datetime(8, 30))
async def test_ongoing_event_with_offset(mock_now, hass, calendar):
"""Test that the offset is taken into account."""