1 """Coordinator for the Islamic prayer times integration."""
3 from __future__
import annotations
5 from datetime
import date, datetime, timedelta
7 from typing
import Any, cast
9 from prayer_times_calculator_offline
import PrayerTimesCalculator
24 DEFAULT_LAT_ADJ_METHOD,
25 DEFAULT_MIDNIGHT_MODE,
30 _LOGGER = logging.getLogger(__name__)
34 """Islamic Prayer Client Object."""
36 config_entry: ConfigEntry
38 def __init__(self, hass: HomeAssistant) ->
None:
39 """Initialize the Islamic Prayer client."""
47 self.
event_unsubevent_unsub: CALLBACK_TYPE |
None =
None
51 """Return the calculation method."""
52 return self.
config_entryconfig_entry.options.get(CONF_CALC_METHOD, DEFAULT_CALC_METHOD)
56 """Return the latitude adjustment method."""
59 CONF_LAT_ADJ_METHOD, DEFAULT_LAT_ADJ_METHOD
65 """Return the midnight mode."""
66 return self.
config_entryconfig_entry.options.get(CONF_MIDNIGHT_MODE, DEFAULT_MIDNIGHT_MODE)
70 """Return the school."""
71 return self.
config_entryconfig_entry.options.get(CONF_SCHOOL, DEFAULT_SCHOOL)
74 """Fetch prayer times for the specified date."""
75 calc = PrayerTimesCalculator(
85 return cast(dict[str, Any], calc.fetch_prayer_times())
89 """Schedule future update for sensors.
91 The least surprising behaviour is to load the next day's prayer times only
92 after the current day's prayers are complete. We will take the fiqhi opinion
93 that Isha should be prayed before Islamic midnight (which may be before or after 12:00 midnight),
94 and thus we will switch to the next day's timings at Islamic midnight.
96 The +1s is to ensure that any automations predicated on the arrival of Islamic midnight will run.
99 _LOGGER.debug(
"Scheduling next update for Islamic prayer times")
106 """Request update from coordinator."""
110 """Update sensors with new prayer times.
112 Prayer time calculations "roll over" at 12:00 midnight - but this does not mean that all prayers
113 occur within that Gregorian calendar day. For instance Jasper, Alta. sees Isha occur after 00:00 in the summer.
114 It is similarly possible (albeit less likely) that Fajr occurs before 00:00.
116 As such, to ensure that no prayer times are "unreachable" (e.g. we always see the Isha timestamp pass before loading the next day's times),
117 we calculate 3 days' worth of times (-1, 0, +1 days) and select the appropriate set based on Islamic midnight.
119 The calculation is inexpensive, so there is no need to cache it.
123 now = dt_util.now().replace(microsecond=0)
129 yesterday_midnight := dt_util.parse_datetime(yesterday_times[
"Midnight"])
130 )
and now <= yesterday_midnight:
131 prayer_times = yesterday_times
133 tomorrow_midnight := dt_util.parse_datetime(today_times[
"Midnight"])
134 )
and now > tomorrow_midnight:
135 prayer_times = tomorrow_times
137 prayer_times = today_times
140 prayer_times.pop(
"date",
None)
142 prayer_times_info: dict[str, datetime] = {}
143 for prayer, time
in prayer_times.items():
144 if prayer_time := dt_util.parse_datetime(time):
145 prayer_times_info[prayer] = dt_util.as_utc(prayer_time)
148 return prayer_times_info
dict[str, Any] get_new_prayer_times(self, date for_date)
dict[str, datetime] _async_update_data(self)
None async_request_update(self, datetime _)
None __init__(self, HomeAssistant hass)
None async_schedule_future_update(self, datetime midnight_dt)
None async_request_refresh(self)
CALLBACK_TYPE async_track_point_in_time(HomeAssistant hass, HassJob[[datetime], Coroutine[Any, Any, None]|None]|Callable[[datetime], Coroutine[Any, Any, None]|None] action, datetime point_in_time)