diff --git a/homeassistant/components/jewish_calendar/const.py b/homeassistant/components/jewish_calendar/const.py index 41d6ef3c5d5..3c5b754fee4 100644 --- a/homeassistant/components/jewish_calendar/const.py +++ b/homeassistant/components/jewish_calendar/const.py @@ -2,6 +2,7 @@ DOMAIN = "jewish_calendar" +ATTR_AFTER_SUNSET = "after_sunset" ATTR_DATE = "date" ATTR_NUSACH = "nusach" diff --git a/homeassistant/components/jewish_calendar/service.py b/homeassistant/components/jewish_calendar/service.py index 9e8e0649358..53d324d6efa 100644 --- a/homeassistant/components/jewish_calendar/service.py +++ b/homeassistant/components/jewish_calendar/service.py @@ -1,6 +1,7 @@ """Services for Jewish Calendar.""" import datetime +import logging from typing import get_args from hdate import HebrewDate @@ -8,7 +9,7 @@ from hdate.omer import Nusach, Omer from hdate.translator import Language, set_language import voluptuous as vol -from homeassistant.const import CONF_LANGUAGE +from homeassistant.const import CONF_LANGUAGE, SUN_EVENT_SUNSET from homeassistant.core import ( HomeAssistant, ServiceCall, @@ -17,16 +18,20 @@ from homeassistant.core import ( ) from homeassistant.helpers import config_validation as cv from homeassistant.helpers.selector import LanguageSelector, LanguageSelectorConfig +from homeassistant.helpers.sun import get_astral_event_date +from homeassistant.util import dt as dt_util -from .const import ATTR_DATE, ATTR_NUSACH, DOMAIN, SERVICE_COUNT_OMER +from .const import ATTR_AFTER_SUNSET, ATTR_DATE, ATTR_NUSACH, DOMAIN, SERVICE_COUNT_OMER +_LOGGER = logging.getLogger(__name__) OMER_SCHEMA = vol.Schema( { - vol.Required(ATTR_DATE, default=datetime.date.today): cv.date, + vol.Optional(ATTR_DATE): cv.date, + vol.Optional(ATTR_AFTER_SUNSET, default=True): cv.boolean, vol.Required(ATTR_NUSACH, default="sfarad"): vol.In( [nusach.name.lower() for nusach in Nusach] ), - vol.Required(CONF_LANGUAGE, default="he"): LanguageSelector( + vol.Optional(CONF_LANGUAGE, default="he"): LanguageSelector( LanguageSelectorConfig(languages=list(get_args(Language))) ), } @@ -36,9 +41,29 @@ OMER_SCHEMA = vol.Schema( def async_setup_services(hass: HomeAssistant) -> None: """Set up the Jewish Calendar services.""" + def is_after_sunset(hass: HomeAssistant) -> bool: + """Determine if the current time is after sunset.""" + now = dt_util.now() + today = now.date() + event_date = get_astral_event_date(hass, SUN_EVENT_SUNSET, today) + if event_date is None: + _LOGGER.error("Can't get sunset event date for %s", today) + raise ValueError("Can't get sunset event date") + sunset = dt_util.as_local(event_date) + _LOGGER.debug("Now: %s Sunset: %s", now, sunset) + return now > sunset + async def get_omer_count(call: ServiceCall) -> ServiceResponse: """Return the Omer blessing for a given date.""" - hebrew_date = HebrewDate.from_gdate(call.data["date"]) + date = call.data.get("date", dt_util.now().date()) + after_sunset = ( + call.data[ATTR_AFTER_SUNSET] + if "date" in call.data + else is_after_sunset(hass) + ) + hebrew_date = HebrewDate.from_gdate( + date + datetime.timedelta(days=int(after_sunset)) + ) nusach = Nusach[call.data["nusach"].upper()] set_language(call.data[CONF_LANGUAGE]) omer = Omer(date=hebrew_date, nusach=nusach) diff --git a/homeassistant/components/jewish_calendar/services.yaml b/homeassistant/components/jewish_calendar/services.yaml index 894fa30fee3..a301857fa66 100644 --- a/homeassistant/components/jewish_calendar/services.yaml +++ b/homeassistant/components/jewish_calendar/services.yaml @@ -1,10 +1,16 @@ count_omer: fields: date: - required: true + required: false example: "2025-04-14" selector: date: + after_sunset: + required: false + example: true + default: true + selector: + boolean: nusach: required: true example: "sfarad" @@ -18,7 +24,7 @@ count_omer: - "adot_mizrah" - "italian" language: - required: true + required: false default: "he" example: "he" selector: diff --git a/homeassistant/components/jewish_calendar/strings.json b/homeassistant/components/jewish_calendar/strings.json index 933d77d2188..dcdfb05f10c 100644 --- a/homeassistant/components/jewish_calendar/strings.json +++ b/homeassistant/components/jewish_calendar/strings.json @@ -65,6 +65,10 @@ "name": "Date", "description": "Date to count the Omer for." }, + "after_sunset": { + "name": "After sunset", + "description": "Uses the next Hebrew day (starting at sunset) for a given date. This indicator is ignored if the Date field is empty." + }, "nusach": { "name": "Nusach", "description": "Nusach to count the Omer in." diff --git a/tests/components/jewish_calendar/test_service.py b/tests/components/jewish_calendar/test_service.py index fd8a96bf69b..4b3f31d11d4 100644 --- a/tests/components/jewish_calendar/test_service.py +++ b/tests/components/jewish_calendar/test_service.py @@ -2,52 +2,84 @@ import datetime as dt -from hdate.translator import Language import pytest from homeassistant.components.jewish_calendar.const import DOMAIN from homeassistant.core import HomeAssistant -from tests.common import MockConfigEntry - @pytest.mark.parametrize( - ("test_date", "nusach", "language", "expected"), + ("test_time", "service_data", "expected"), [ - pytest.param(dt.date(2025, 3, 20), "sfarad", "he", "", id="no_blessing"), pytest.param( - dt.date(2025, 5, 20), - "ashkenaz", - "he", + dt.datetime(2025, 3, 20, 21, 0), + { + "date": dt.date(2025, 3, 20), + "nusach": "sfarad", + "language": "he", + "after_sunset": False, + }, + "", + id="no_blessing", + ), + pytest.param( + dt.datetime(2025, 3, 20, 21, 0), + { + "date": dt.date(2025, 5, 20), + "nusach": "ashkenaz", + "language": "he", + "after_sunset": False, + }, "היום שבעה ושלושים יום שהם חמישה שבועות ושני ימים בעומר", id="ahskenaz-hebrew", ), pytest.param( - dt.date(2025, 5, 20), - "sfarad", - "en", + dt.datetime(2025, 3, 20, 21, 0), + { + "date": dt.date(2025, 5, 20), + "nusach": "sfarad", + "language": "en", + "after_sunset": True, + }, + "Today is the thirty-eighth day, which are five weeks and three days of the Omer", + id="sefarad-english-after-sunset", + ), + pytest.param( + dt.datetime(2025, 3, 20, 21, 0), + { + "date": dt.date(2025, 5, 20), + "nusach": "sfarad", + "language": "en", + "after_sunset": False, + }, "Today is the thirty-seventh day, which are five weeks and two days of the Omer", - id="sefarad-english", + id="sefarad-english-before-sunset", + ), + pytest.param( + dt.datetime(2025, 5, 20, 21, 0), + {"nusach": "sfarad", "language": "en"}, + "Today is the thirty-eighth day, which are five weeks and three days of the Omer", + id="sefarad-english-after-sunset-without-date", + ), + pytest.param( + dt.datetime(2025, 5, 20, 6, 0), + {"nusach": "sfarad"}, + "היום שבעה ושלושים יום שהם חמישה שבועות ושני ימים לעומר", + id="sefarad-english-before-sunset-without-date", ), ], + indirect=["test_time"], ) +@pytest.mark.usefixtures("setup_at_time") async def test_get_omer_blessing( - hass: HomeAssistant, - config_entry: MockConfigEntry, - test_date: dt.date, - nusach: str, - language: Language, - expected: str, + hass: HomeAssistant, service_data: dict[str, str | dt.date | bool], expected: str ) -> None: """Test get omer blessing.""" - config_entry.add_to_hass(hass) - await hass.config_entries.async_setup(config_entry.entry_id) - await hass.async_block_till_done() result = await hass.services.async_call( DOMAIN, "count_omer", - {"date": test_date, "nusach": nusach, "language": language}, + service_data, blocking=True, return_response=True, )