mirror of
https://github.com/home-assistant/core.git
synced 2025-09-04 12:21:36 +02:00
Add calendar to Workday
This commit is contained in:
98
homeassistant/components/workday/calendar.py
Normal file
98
homeassistant/components/workday/calendar.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""Workday Calendar."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from holidays import HolidayBase
|
||||
|
||||
from homeassistant.components.calendar import CalendarEntity, CalendarEvent
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import WorkdayConfigEntry
|
||||
from .const import CONF_EXCLUDES, CONF_OFFSET, CONF_WORKDAYS
|
||||
from .entity import BaseWorkdayEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: WorkdayConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the Holiday Calendar config entry."""
|
||||
days_offset: int = int(entry.options[CONF_OFFSET])
|
||||
excludes: list[str] = entry.options[CONF_EXCLUDES]
|
||||
sensor_name: str = entry.options[CONF_NAME]
|
||||
workdays: list[str] = entry.options[CONF_WORKDAYS]
|
||||
obj_holidays = entry.runtime_data
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
WorkdayCalendarEntity(
|
||||
obj_holidays,
|
||||
workdays,
|
||||
excludes,
|
||||
days_offset,
|
||||
sensor_name,
|
||||
entry.entry_id,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class WorkdayCalendarEntity(BaseWorkdayEntity, CalendarEntity):
|
||||
"""Representation of a Wokrday Calendar."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
obj_holidays: HolidayBase,
|
||||
workdays: list[str],
|
||||
excludes: list[str],
|
||||
days_offset: int,
|
||||
name: str,
|
||||
entry_id: str,
|
||||
) -> None:
|
||||
"""Initialize WorkdayCalendarEntity."""
|
||||
super().__init__(
|
||||
obj_holidays,
|
||||
workdays,
|
||||
excludes,
|
||||
days_offset,
|
||||
name,
|
||||
entry_id,
|
||||
)
|
||||
self._attr_unique_id = f"{entry_id}-calender"
|
||||
self._attr_event = None
|
||||
self.event_list: list[CalendarEvent] = []
|
||||
self._name = name
|
||||
|
||||
def update_data(self, now: datetime) -> None:
|
||||
"""Update data."""
|
||||
event_list = []
|
||||
for i in range(365):
|
||||
future_date = now.date() + timedelta(days=i)
|
||||
if self.date_is_workday(future_date):
|
||||
event = CalendarEvent(
|
||||
summary=self._name,
|
||||
start=future_date,
|
||||
end=future_date,
|
||||
)
|
||||
event_list.append(event)
|
||||
self.event_list = event_list
|
||||
|
||||
@property
|
||||
def event(self) -> CalendarEvent | None:
|
||||
"""Return the next upcoming event."""
|
||||
return (
|
||||
sorted(self.event_list, key=lambda e: e.start)[0]
|
||||
if self.event_list
|
||||
else None
|
||||
)
|
||||
|
||||
async def async_get_events(
|
||||
self, hass: HomeAssistant, start_date: datetime, end_date: datetime
|
||||
) -> list[CalendarEvent]:
|
||||
"""Get all events in a specific time frame."""
|
||||
return self.event_list
|
@@ -11,7 +11,7 @@ LOGGER = logging.getLogger(__package__)
|
||||
ALLOWED_DAYS = [*WEEKDAYS, "holiday"]
|
||||
|
||||
DOMAIN = "workday"
|
||||
PLATFORMS = [Platform.BINARY_SENSOR]
|
||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.CALENDAR]
|
||||
|
||||
CONF_PROVINCE = "province"
|
||||
CONF_WORKDAYS = "workdays"
|
||||
|
@@ -212,6 +212,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"calendar": {
|
||||
"workday": {
|
||||
"name": "[%key:component::calendar::title%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
|
79
tests/components/workday/test_calendar.py
Normal file
79
tests/components/workday/test_calendar.py
Normal file
@@ -0,0 +1,79 @@
|
||||
"""Tests for calendar platform of Workday integration."""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.calendar import (
|
||||
DOMAIN as CALENDAR_DOMAIN,
|
||||
SERVICE_GET_EVENTS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import TEST_CONFIG_WITH_PROVINCE, init_integration
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"time_zone", ["Asia/Tokyo", "Europe/Berlin", "America/Chicago", "US/Hawaii"]
|
||||
)
|
||||
async def test_holiday_calendar_entity(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
time_zone: str,
|
||||
) -> None:
|
||||
"""Test HolidayCalendarEntity functionality."""
|
||||
await hass.config.async_set_time_zone(time_zone)
|
||||
zone = await dt_util.async_get_time_zone(time_zone)
|
||||
freezer.move_to(datetime(2023, 1, 1, 0, 1, 1, tzinfo=zone)) # New Years Day
|
||||
await init_integration(hass, TEST_CONFIG_WITH_PROVINCE)
|
||||
|
||||
await async_setup_component(hass, "calendar", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
response = await hass.services.async_call(
|
||||
CALENDAR_DOMAIN,
|
||||
SERVICE_GET_EVENTS,
|
||||
{
|
||||
"entity_id": "calendar.workday_sensor_calendar",
|
||||
"end_date_time": dt_util.now() + timedelta(hours=1),
|
||||
},
|
||||
blocking=True,
|
||||
return_response=True,
|
||||
)
|
||||
assert {
|
||||
"end": "2023-01-01",
|
||||
"start": "2023-01-02",
|
||||
"summary": "Workday Sensor",
|
||||
} not in response["calendar.workday_sensor_calendar"]["events"]
|
||||
assert {
|
||||
"end": "2023-01-04",
|
||||
"start": "2023-01-03",
|
||||
"summary": "Workday Sensor",
|
||||
} in response["calendar.workday_sensor_calendar"]["events"]
|
||||
|
||||
state = hass.states.get("calendar.workday_sensor_calendar")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
freezer.move_to(
|
||||
datetime(2023, 1, 2, 0, 1, 1, tzinfo=zone)
|
||||
) # Day after New Years Day
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("calendar.workday_sensor_calendar")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
freezer.move_to(datetime(2023, 1, 7, 0, 1, 1, tzinfo=zone)) # Workday
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("calendar.workday_sensor_calendar")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
Reference in New Issue
Block a user