Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Handle Incalculable Zmanim
  • Loading branch information
dickermoshe committed Jul 9, 2023
commit b89ec6f1554c8ae2e895bf80b8904f39dde48eee
7 changes: 5 additions & 2 deletions zmanim/astronomical_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def utc_sunset(self, zenith: float) -> Optional[float]:
def utc_sea_level_sunset(self, zenith: float) -> Optional[float]:
return self.astronomical_calculator.utc_sunset(self._adjusted_date(), self.geo_location, zenith, adjust_for_elevation=False)

def temporal_hour(self, sunrise: Optional[datetime] = __sentinel, sunset: Optional[datetime] = __sentinel) -> Optional[float]:
def temporal_hour(self, sunrise: Optional[datetime] = __sentinel, sunset: Optional[datetime] = __sentinel) -> Optional[float]: # type: ignore
if sunrise == self.__sentinel:
sunrise = self.sea_level_sunrise()
if sunset == self.__sentinel:
Expand All @@ -79,7 +79,10 @@ def sun_transit(self) -> Optional[datetime]:
sunset = self.sea_level_sunset()
if sunrise is None or sunset is None:
return None
noon_hour = (self.temporal_hour(sunrise, sunset) / self.HOUR_MILLIS) * 6.0
temporal_hour = self.temporal_hour(sunrise, sunset)
if temporal_hour is None:
return None
noon_hour = (temporal_hour / self.HOUR_MILLIS) * 6.0
return sunrise + timedelta(noon_hour / 24.0)

def _date_time_from_time_of_day(self, time_of_day: Optional[float], mode: str) -> Optional[datetime]:
Expand Down
22 changes: 16 additions & 6 deletions zmanim/util/geo_location.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Optional
from datetime import datetime, tzinfo
from typing import Optional, Union

from dateutil import tz

Expand Down Expand Up @@ -62,13 +62,16 @@ def longitude(self, longitude):
raise TypeError("input must be a number or a list in the format 'degrees,minutes,seconds,direction'")

@property
def time_zone(self) -> tz.tzfile:
def time_zone(self) -> Union[tz.tzfile,tzinfo]:
return self.__time_zone

@time_zone.setter
def time_zone(self, time_zone):
if isinstance(time_zone, str):
self.__time_zone = tz.gettz(time_zone)
time_zone = tz.gettz(time_zone)
if time_zone is None:
raise ValueError("invalid time zone")
self.__time_zone = time_zone
elif isinstance(time_zone, tz.tzfile):
self.__time_zone = time_zone
else:
Expand Down Expand Up @@ -109,7 +112,14 @@ def local_mean_time_offset(self) -> float:

def standard_time_offset(self) -> int:
now = datetime.now(tz=self.time_zone)
return int((now.utcoffset() - now.dst()).total_seconds()) * 1000
utcoffset = now.utcoffset()
dst = now.dst()
if utcoffset is None or dst is None:
raise ValueError("Could not determine time zone offset or DST")
return int((utcoffset - dst).total_seconds()) * 1000

def time_zone_offset_at(self, utc_time: datetime) -> float:
return utc_time.astimezone(self.time_zone).utcoffset().total_seconds() / 3600.0
utcoffset = utc_time.astimezone(self.time_zone).utcoffset()
if utcoffset is None:
raise ValueError("Could not determine time zone offset")
return utcoffset.total_seconds() / 3600.0
37 changes: 28 additions & 9 deletions zmanim/zmanim_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


class ZmanimCalendar(AstronomicalCalendar):
def __init__(self, candle_lighting_offset: int = None, *args, **kwargs):
def __init__(self, candle_lighting_offset: Optional[int] = None, *args, **kwargs):
super(ZmanimCalendar, self).__init__(*args, **kwargs)
self.candle_lighting_offset = 18 if candle_lighting_offset is None else candle_lighting_offset
self.use_elevation = False
Expand Down Expand Up @@ -56,14 +56,22 @@ def chatzos(self) -> Optional[datetime]:
def candle_lighting(self) -> Optional[datetime]:
return self._offset_by_minutes(self.sea_level_sunset(), -self.candle_lighting_offset)

def sof_zman_shma(self, day_start: datetime, day_end: datetime) -> datetime:
def sof_zman_shma(self, day_start: datetime, day_end: datetime) -> Optional[datetime]:
return self._shaos_into_day(day_start, day_end, 3)

def sof_zman_shma_gra(self) -> datetime:
return self.sof_zman_shma(self.elevation_adjusted_sunrise(), self.elevation_adjusted_sunset())
def sof_zman_shma_gra(self) -> Optional[datetime]:
elevation_adjusted_sunrise = self.elevation_adjusted_sunrise()
elevation_adjusted_sunset = self.elevation_adjusted_sunset()
if elevation_adjusted_sunrise is None or elevation_adjusted_sunset is None:
return None
return self.sof_zman_shma(elevation_adjusted_sunrise, elevation_adjusted_sunset)

def sof_zman_shma_mga(self) -> datetime:
return self.sof_zman_shma(self.alos_72(), self.tzais_72())
def sof_zman_shma_mga(self) -> Optional[datetime]:
alos_72 = self.alos_72()
tzais_72 = self.tzais_72()
if alos_72 is None or tzais_72 is None:
return None
return self.sof_zman_shma(alos_72, tzais_72)

def sof_zman_tfila(self, day_start: Optional[datetime], day_end: Optional[datetime]) -> Optional[datetime]:
return self._shaos_into_day(day_start, day_end, 4)
Expand Down Expand Up @@ -111,17 +119,25 @@ def shaah_zmanis_by_degrees_and_offset(self, degrees: float, offset: float) -> O
opts = {'degrees': degrees, 'offset': offset}
return self.shaah_zmanis(self.alos(opts), self.tzais(opts))

def is_assur_bemelacha(self, current_time: datetime, tzais=None, in_israel: Optional[bool]=False):
def is_assur_bemelacha(self, current_time: datetime, tzais=None, in_israel: Optional[bool]=False) -> Optional[bool]:
if tzais is None:
tzais_time = self.tzais()
elif isinstance(tzais, dict):
tzais_time = self.tzais(tzais)
else:
tzais_time = tzais

if tzais_time is None:
return None

elevation_adjusted_sunset = self.elevation_adjusted_sunset()
if elevation_adjusted_sunset is None:
return None

jewish_calendar = JewishCalendar(current_time.date())
jewish_calendar.in_israel = in_israel
return (current_time <= tzais_time and jewish_calendar.is_assur_bemelacha()) or \
(current_time >= self.elevation_adjusted_sunset() and jewish_calendar.is_tomorrow_assur_bemelacha())
(current_time >= elevation_adjusted_sunset and jewish_calendar.is_tomorrow_assur_bemelacha())

def _shaos_into_day(self, day_start: Optional[datetime], day_end: Optional[datetime], shaos: float) -> Optional[datetime]:
shaah_zmanis = self.temporal_hour(day_start, day_end)
Expand All @@ -143,5 +159,8 @@ def _offset_by_minutes(self, time: Optional[datetime], minutes: float) -> Option
def _offset_by_minutes_zmanis(self, time: Optional[datetime], minutes: float) -> Optional[datetime]:
if time is None:
return None
shaah_zmanis_skew = self.shaah_zmanis_gra() / self.HOUR_MILLIS
shaah_zmanis_gra = self.shaah_zmanis_gra()
if shaah_zmanis_gra is None:
return None
shaah_zmanis_skew = shaah_zmanis_gra / self.HOUR_MILLIS
return time + timedelta(minutes=minutes*shaah_zmanis_skew)