Skip to main content

rust_zmanim/complex_zmanim_calendar/
czc_struct.rs

1use crate::{
2    util::geolocation::GeoLocation,
3    zmanim_calculator::{
4        self,
5        ZmanOffset::{self, Degrees, Minutes, MinutesZmaniyos},
6    },
7};
8
9use chrono::{DateTime, TimeDelta};
10use chrono_tz::Tz;
11use pastey::paste;
12
13/// Struct to store a 4-dimensional location and settings, to simplify getting
14/// many *zmanim* for the same location. Has premade methods for many common
15/// (and uncommon) *zmanim*. (see `impl` block)
16#[derive(Debug, Clone, Copy, PartialEq)]
17pub struct ComplexZmanimCalendar {
18    /// Location at which to calculate *zmanim*
19    pub geo_location: GeoLocation,
20
21    /// Day for which to calculate *zmanim*. Time does not (should not) affect
22    /// the calculations
23    pub date: DateTime<Tz>,
24
25    /// When to account for elevation. See [`UseElevation`]
26    pub use_elevation: UseElevation,
27}
28
29/// Where unspecified, when sunrise and sunset are mentioned in the calculation
30/// of other *zmanim*, they will be sea-level or elevation-based depending on
31/// the value of `use_elevation`
32///
33/// **Elevation-based *zmanim* (even sunrise and sunset) should not be used
34/// *lekula* without the guidance of a *posek***. See the documentation of
35/// [`zmanim_calculator`] for more details.
36///
37/// Many of the methods return `None` if the sun does not reach the specified
38/// position below the horizon at this location and date (common in polar
39/// regions).
40impl ComplexZmanimCalendar {
41    // Basics
42    /// Returns *alos hashachar* (dawn) based on either declination of the sun
43    /// below the horizon, a fixed time offset, or a minutes *zmaniyos*
44    /// (temporal minutes) offset before sunrise
45    #[must_use]
46    pub fn alos(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
47        let use_elevation = self.use_elevation.to_bool(false);
48        zmanim_calculator::alos(&self.date, &self.geo_location, use_elevation, offset)
49    }
50
51    /// Returns sea level sunrise
52    #[must_use]
53    pub fn sea_level_sunrise(&self) -> Option<DateTime<Tz>> {
54        zmanim_calculator::hanetz(&self.date, &self.geo_location, false)
55    }
56
57    /// Returns sea level sunset
58    #[must_use]
59    pub fn sea_level_sunset(&self) -> Option<DateTime<Tz>> {
60        zmanim_calculator::shkia(&self.date, &self.geo_location, false)
61    }
62
63    /// Returns elevation-adjusted sunrise
64    #[must_use]
65    pub fn elevation_sunrise(&self) -> Option<DateTime<Tz>> {
66        zmanim_calculator::hanetz(&self.date, &self.geo_location, true)
67    }
68
69    /// Returns elevation-adjusted sunset
70    #[must_use]
71    pub fn elevation_sunset(&self) -> Option<DateTime<Tz>> {
72        zmanim_calculator::shkia(&self.date, &self.geo_location, true)
73    }
74
75    /// Returns *hanetz*, or sunrise. Will be elevation-adjusted or not
76    /// depending on `use_elevation`
77    #[must_use]
78    pub fn hanetz(&self) -> Option<DateTime<Tz>> {
79        let use_elevation = self.use_elevation.to_bool(true);
80        zmanim_calculator::hanetz(&self.date, &self.geo_location, use_elevation)
81    }
82
83    /// Returns *shkia*, or sunset. Will be elevation-adjusted or not depending
84    /// on `use_elevation`
85    #[must_use]
86    pub fn shkia(&self) -> Option<DateTime<Tz>> {
87        let use_elevation = self.use_elevation.to_bool(true);
88        zmanim_calculator::shkia(&self.date, &self.geo_location, use_elevation)
89    }
90
91    /// Returns the latest *zman krias shema* (time to recite *Shema* in the
92    /// morning) according to the opinion of the *Magen Avraham* (MGA) based on
93    /// *alos* and *tzais* being given offset from sunrise and sunset,
94    /// respectively.
95    #[must_use]
96    pub fn sof_zman_shema_mga(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
97        Some(zmanim_calculator::sof_zman_shema(
98            &self.alos(offset)?,
99            &self.tzais(offset)?,
100        ))
101    }
102
103    /// Returns the latest *zman tefila* (time to recite *shacharis* in the
104    /// morning) according to the opinion of the *Magen Avraham* (MGA) based on
105    /// *alos* and *tzais* being the given offset from sunrise and sunset,
106    /// respectively.
107    #[must_use]
108    pub fn sof_zman_tefila_mga(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
109        Some(zmanim_calculator::sof_zman_tefila(
110            &self.alos(offset)?,
111            &self.tzais(offset)?,
112        ))
113    }
114
115    /// Returns the latest *zman biur chametz* (the latest time for burning
116    /// *chametz* on *Erev Pesach*) according to the opinion of the *Magen
117    /// Avraham* (MGA) based on *alos* and *tzais* being the given offset
118    /// from sunrise and sunset, respectively.
119    #[must_use]
120    pub fn sof_zman_biur_chametz_mga(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
121        Some(zmanim_calculator::sof_zman_biur_chametz(
122            &self.alos(offset)?,
123            &self.tzais(offset)?,
124        ))
125    }
126
127    /// Returns Astronomical *chatzos* (noon)
128    #[must_use]
129    pub fn chatzos(&self) -> Option<DateTime<Tz>> {
130        zmanim_calculator::chatzos(&self.date, &self.geo_location)
131    }
132
133    /// Returns Astronomical *chatzos halayla* (midnight)
134    #[must_use]
135    pub fn chatzos_halayla(&self) -> Option<DateTime<Tz>> {
136        zmanim_calculator::chatzos_halayla(&self.date, &self.geo_location)
137    }
138
139    /// Returns *mincha gedola* according to the opinion of the *Magen Avraham*
140    /// (MGA) based on *alos* and *tzais* being the given offset from sunrise
141    /// and sunset, respectively.
142    #[must_use]
143    pub fn mincha_gedola_mga(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
144        Some(zmanim_calculator::mincha_gedola(
145            &self.alos(offset)?,
146            &self.tzais(offset)?,
147        ))
148    }
149
150    /// Returns *samuch lemincha ketana* according to the opinion of the *Magen
151    /// Avraham* (MGA) based on *alos* and *tzais* being the given offset
152    /// from sunrise and sunset, respectively.
153    #[must_use]
154    pub fn samuch_lemincha_ketana_mga(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
155        Some(zmanim_calculator::samuch_lemincha_ketana(
156            &self.alos(offset)?,
157            &self.tzais(offset)?,
158        ))
159    }
160
161    /// Returns *mincha ketana* according to the opinion of the *Magen Avraham*
162    /// (MGA) based on *alos* and *tzais* being the given offset from sunrise
163    /// and sunset, respectively.
164    #[must_use]
165    pub fn mincha_ketana_mga(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
166        Some(zmanim_calculator::mincha_ketana(
167            &self.alos(offset)?,
168            &self.tzais(offset)?,
169        ))
170    }
171
172    /// Returns *plag hamincha* according to the opinion of the *Magen Avraham*
173    /// (MGA) based on *alos* and *tzais* being the given offset from sunrise
174    /// and sunset, respectively.
175    #[must_use]
176    pub fn plag_mga(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
177        Some(zmanim_calculator::plag_hamincha(
178            &self.alos(offset)?,
179            &self.tzais(offset)?,
180        ))
181    }
182
183    /// Returns *mincha gedola* calculated as 30 minutes after *chatzos* and not
184    /// 1/2 of a *shaah zmanis* after *chatzos* as calculated by
185    /// [`zmanim_calculator::mincha_gedola`]. See
186    /// [`zmanim_calculator::mincha_gedola_30_minutes`] for more details
187    #[must_use]
188    pub fn mincha_gedola_30_minutes(&self) -> Option<DateTime<Tz>> {
189        zmanim_calculator::mincha_gedola_30_minutes(&self.date, &self.geo_location)
190    }
191
192    /// Returns *tzais* (nightfall) based on either declination of the sun below
193    /// the horizon, a fixed time offset, or a minutes *zmaniyos* (temporal
194    /// minutes) offset after sunset
195    #[must_use]
196    pub fn tzais(&self, offset: &ZmanOffset) -> Option<DateTime<Tz>> {
197        let use_elevation = self.use_elevation.to_bool(false);
198        zmanim_calculator::tzais(&self.date, &self.geo_location, use_elevation, offset)
199    }
200
201    /// Returns *shaah zmanis* (temporal hour) according to the opinion of the
202    /// *Magen Avraham* (MGA) based on *alos* and *tzais* being the given
203    /// offset from sunrise and sunset, respectively.
204    #[must_use]
205    pub fn shaah_zmanis_mga(&self, offset: &ZmanOffset) -> Option<TimeDelta> {
206        Some(zmanim_calculator::shaah_zmanis(
207            &self.alos(offset)?,
208            &self.tzais(offset)?,
209        ))
210    }
211
212    // GRA
213    /// Returns the latest *zman shema* (time to recite *Shema* in the morning)
214    /// that is 3 *shaos zmaniyos* (solar hours) after
215    /// sunrise according the GRA. The day is
216    /// calculated from sunrise to sunset.
217    #[must_use]
218    pub fn sof_zman_shema_gra(&self) -> Option<DateTime<Tz>> {
219        Some(zmanim_calculator::sof_zman_shema(
220            &self.hanetz()?,
221            &self.shkia()?,
222        ))
223    }
224
225    /// Returns the latest *zman tefila* (time to recite *shacharis* in the
226    /// morning) that is 4 *shaos zmaniyos* (solar hours) after
227    /// sunrise according GRA.
228    /// The day is calculated from sunrise to sunset
229    #[must_use]
230    pub fn sof_zman_tefila_gra(&self) -> Option<DateTime<Tz>> {
231        Some(zmanim_calculator::sof_zman_tefila(
232            &self.hanetz()?,
233            &self.shkia()?,
234        ))
235    }
236
237    /// Returns the latest time for burning *chametz* on *Erev
238    /// Pesach* according to the opinion of the GRA. This time is 5 hours into
239    /// the day based on the opinion of the GRA that the day is calculated from
240    /// sunrise to sunset. Since this library does not implement a calendar,
241    /// this method will return the *zman* any day of the year.
242    #[must_use]
243    pub fn sof_zman_biur_chametz_gra(&self) -> Option<DateTime<Tz>> {
244        Some(self.hanetz()? + (self.shaah_zmanis_gra()? * 5))
245    }
246
247    /// Returns *mincha gedola* calculated as 6.5 * *shaos zmaniyos*
248    /// (solar hours) after sunrise, according to the GRA.
249    #[must_use]
250    pub fn mincha_gedola_gra(&self) -> Option<DateTime<Tz>> {
251        Some(zmanim_calculator::mincha_gedola(
252            &self.hanetz()?,
253            &self.shkia()?,
254        ))
255    }
256
257    /// Returns the later of
258    /// [`mincha_gedola_gra`](ComplexZmanimCalendar::mincha_gedola_gra)
259    /// and
260    /// [`mincha_gedola_30_minutes`](ComplexZmanimCalendar::mincha_gedola_30_minutes)
261    /// . In the winter when 1/2 of a
262    /// [GRA *shaah zmanis*](ComplexZmanimCalendar::shaah_zmanis_gra)
263    /// is less than 30 minutes
264    /// [`mincha_gedola_30_minutes`](ComplexZmanimCalendar::mincha_gedola_30_minutes)
265    /// will be returned, otherwise
266    /// [`mincha_gedola_gra`](ComplexZmanimCalendar::mincha_gedola_gra)
267    ///  will be returned
268    #[must_use]
269    pub fn mincha_gedola_gra_greater_than_30_minutes(&self) -> Option<DateTime<Tz>> {
270        let mg_30 = self.mincha_gedola_30_minutes()?;
271        let mg_gra = self.mincha_gedola_gra()?;
272        Some(if mg_30 > mg_gra { mg_30 } else { mg_gra })
273    }
274
275    /// A method for calculating *samuch lemincha ketana*, / near *mincha
276    /// ketana* time that is half an hour before [*mincha
277    /// ketana*](ComplexZmanimCalendar::mincha_ketana_gra) or is 9 *shaos
278    /// zmaniyos* (solar hours) after sunrise, calculated according to the GRA
279    /// using a day starting at sunrise and ending at sunset. This is the
280    /// time that eating or other activity can't begin prior to praying
281    /// *mincha*. See the *Mechaber* and *Mishna Berurah* 232 and 249:2.
282    #[must_use]
283    pub fn samuch_lemincha_ketana_gra(&self) -> Option<DateTime<Tz>> {
284        Some(self.hanetz()? + (self.shaah_zmanis_gra()? * 9))
285    }
286
287    /// Returns *mincha ketana* calculated as 9.5 * *shaos zmaniyos*
288    /// (solar hours) after sunrise, according to the GRA.
289    #[must_use]
290    pub fn mincha_ketana_gra(&self) -> Option<DateTime<Tz>> {
291        Some(zmanim_calculator::mincha_ketana(
292            &self.hanetz()?,
293            &self.shkia()?,
294        ))
295    }
296
297    /// Returns *plag hamincha* calculated as 10.75 * *shaos zmaniyos*
298    /// (solar hours) after sunrise, according to the GRA.
299    #[must_use]
300    pub fn plag_gra(&self) -> Option<DateTime<Tz>> {
301        Some(zmanim_calculator::plag_hamincha(
302            &self.hanetz()?,
303            &self.shkia()?,
304        ))
305    }
306
307    /// Returns a *shaah zmanis* according to the opinion of the GRA.
308    /// This calculation divides the day based on the opinion of the *GRA* that
309    /// the day runs from from sunrise to sunset. The day is split into 12 equal
310    /// parts with each one being a *shaah zmanis*
311    #[must_use]
312    pub fn shaah_zmanis_gra(&self) -> Option<TimeDelta> {
313        Some(zmanim_calculator::shaah_zmanis(
314            &self.hanetz()?,
315            &self.shkia()?,
316        ))
317    }
318
319    // Baal HaTanya
320    /// Returns the *Baal Hatanya*'s *alos* (dawn) calculated as the time when
321    /// the sun is 16.9&deg; below the eastern geometric horizon before sunrise.
322    /// It is based on the calculation that the time between dawn and
323    /// [*hanetz amiti*](ComplexZmanimCalendar::hanetz_amiti_baal_hatanya)
324    /// (sunrise) is 72 minutes, the time that is takes to walk 4 *mil* at
325    /// 18 minutes a *mil* (*Rambam* and others). The sun's position at 72
326    /// minutes before *hanetz amiti* (sunrise) in Jerusalem around the
327    /// equinox / equilux is 16.9&deg; below geometric zenith.
328    #[must_use]
329    pub fn alos_baal_hatanya(&self) -> Option<DateTime<Tz>> {
330        self.alos(&Degrees(16.9))
331    }
332
333    /// **Note: *hanetz amiti* is used only for
334    /// calculating certain other *zmanim*. For practical purposes, daytime
335    /// *mitzvos* like *shofar* and *lulav* should not be done until after the
336    /// normal time for [*hanetz*](ComplexZmanimCalendar::hanetz).**
337    ///
338    /// Returns the *Baal Hatanya*'s *hanetz amiti* (sunrise) without elevation
339    /// adjustment. This forms the base for the *Baal Hatanya*'s dawn-based
340    /// calculations that are calculated as a dip below the horizon before
341    /// sunrise. According to the *Baal Hatanya*, *hanetz amiti*, or true
342    /// (halachic) sunrise, is when the top of the sun's disk is visible at an
343    /// elevation similar to the mountains of *Eretz Yisrael*. The time is
344    /// calculated as the point at which the center of the sun's disk is
345    /// 1.583&deg; below the horizon. This degree-based calculation can be found
346    /// in Rabbi Shalom DovBer Levine's commentary on The *Baal Hatanya*'s
347    /// *Seder Hachnasas Shabbos*. From an elevation of 546 meters, the top of
348    /// *Har Hacarmel*, the sun disappears when it is 1&deg; 35' or 1.583&deg;
349    /// below the sea level horizon. This in turn is based on the *Gemara
350    /// Shabbos* 35a. There are other opinions brought down by Rabbi Levine,
351    /// including Rabbi Yosef Yitzchok Feigelstock who calculates it as the
352    /// degrees below the horizon 4 minutes after sunset in *Yerushalayim* (on
353    /// the equinox). That is brought down as 1.583&deg;. This is identical to
354    /// the 1&deg; 35' *zman* and is probably a typo and should be 1.683&deg;.
355    /// These calculations are used by most *Chabad* calendars that use the
356    /// *Baal Hatanya*'s *zmanim*.
357    #[must_use]
358    pub fn hanetz_amiti_baal_hatanya(&self) -> Option<DateTime<Tz>> {
359        self.alos(&Degrees(1.583))
360    }
361
362    /// **Note: *shkiah amiti* is used only for calculating certain other
363    /// *zmanim*. For practical purposes, all daytime *mitzvos* should be
364    /// completed before the normal time for
365    /// [*shkiah*](ComplexZmanimCalendar::shkia).**
366    ///
367    /// Returns the *Baal Hatanya*'s *shkiah amiti* (sunset) without elevation
368    /// adjustment. This forms the base for the *Baal Hatanya*'s dusk-based
369    /// calculations that are calculated as a dip below the horizon after
370    /// sunset. According to the *Baal Hatanya*, *shkiah amiti*, true (halachic)
371    /// sunset, is when the top of the sun's disk disappears from view at an
372    /// elevation similar to the mountains of *Eretz Yisrael*. This time is
373    /// calculated as the point at which the center of the sun's disk is 1.583
374    /// degrees below the horizon.
375    #[must_use]
376    pub fn shkia_amiti_baal_hatanya(&self) -> Option<DateTime<Tz>> {
377        self.tzais(&Degrees(1.583))
378    }
379
380    /// Returns the *Baal Hatanya*'s a *shaah zmanis* (temporal hour). This
381    /// forms the base for the *Baal Hatanya*'s day based calculations that are
382    /// calculated as a 1.583&deg; dip below the horizon after sunset. According
383    /// to the *Baal Hatanya*, *shkiah amiti*, true (halachic) sunset, is when
384    /// the top of the sun's disk disappears from view at an elevation similar
385    /// to the mountains of *Eretz Yisrael*. This time is calculated as the
386    /// point at which the center of the sun's disk is 1.583 degrees below the
387    /// horizon. The calculations are based on a day from [*hanetz
388    /// amiti*](ComplexZmanimCalendar::hanetz_amiti_baal_hatanya) to
389    /// [*shkiah amiti*](ComplexZmanimCalendar::shkia_amiti_baal_hatanya). The
390    /// day is split into 12 equal parts with each one being a *shaah
391    /// zmanis*.
392    #[must_use]
393    pub fn shaah_zmanis_baal_hatanya(&self) -> Option<TimeDelta> {
394        self.shaah_zmanis_mga(&Degrees(1.583))
395    }
396
397    /// Returns the the *Baal Hatanya*'s *sof *zman* krias shema*
398    /// (latest time to recite *Shema* in the morning). This time is 3
399    /// of the [*Baal Hatanya*'s temporal
400    /// hours](ComplexZmanimCalendar::shaah_zmanis_baal_hatanya) after [*hanetz
401    /// amiti*](ComplexZmanimCalendar::hanetz_amiti_baal_hatanya) (sunrise)
402    /// based on the opinion of the *Baal Hatanya* that the day is
403    /// calculated from sunrise to sunset.
404    #[must_use]
405    pub fn sof_zman_shema_baal_hatanya(&self) -> Option<DateTime<Tz>> {
406        self.sof_zman_shema_mga(&Degrees(1.583))
407    }
408
409    /// Returns the the *Baal Hatanya*'s *sof *zman* tefila* (latest
410    /// time to recite the morning prayers). This time is 4 of the [*Baal
411    /// Hatanya*'s temporal
412    /// hours](ComplexZmanimCalendar::shaah_zmanis_baal_hatanya) after [*hanetz
413    /// amiti*](ComplexZmanimCalendar::hanetz_amiti_baal_hatanya) (sunrise)
414    /// based on the opinion of the *Baal Hatanya* that the day is
415    /// calculated from sunrise to sunset.
416    #[must_use]
417    pub fn sof_zman_tefila_baal_hatanya(&self) -> Option<DateTime<Tz>> {
418        self.sof_zman_tefila_mga(&Degrees(1.583))
419    }
420
421    /// Returns the latest time for burning *chametz* on *Erev
422    /// Pesach* according to the opinion of the Baal Hatanya. This time is 5
423    /// of the [*Baal Hatanya*'s temporal
424    /// hours](ComplexZmanimCalendar::shaah_zmanis_baal_hatanya) after [*hanetz
425    /// amiti*](ComplexZmanimCalendar::hanetz_amiti_baal_hatanya) (sunrise)
426    /// based on the opinion of the *Baal Hatanya* that the day is
427    /// calculated from sunrise to sunset. Since this library does not
428    /// implement a calendar, this method will return the *zman* any day of
429    /// the year.
430    #[must_use]
431    pub fn sof_zman_biur_chametz_baal_hatanya(&self) -> Option<DateTime<Tz>> {
432        self.sof_zman_biur_chametz_mga(&Degrees(1.583))
433    }
434
435    /// Returns the the *Baal Hatanya*'s *mincha gedola*. *Mincha
436    /// gedola* is the earliest time one can pray *mincha*. The *Rambam* is
437    /// of the opinion that it is better to delay *mincha* until *mincha
438    /// ketana* while the *Rash*, *Tur*, GRA and others are of the opinion
439    /// that *mincha* can be prayed *lechatchila* starting at *mincha
440    /// gedola*. This is calculated as 6.5 of the [*Baal Hatanya*'s temporal
441    /// hours](ComplexZmanimCalendar::shaah_zmanis_baal_hatanya) after [*hanetz
442    /// amiti*](ComplexZmanimCalendar::hanetz_amiti_baal_hatanya) (sunrise).
443    /// This calculation is based on the opinion of the *Baal Hatanya* that
444    /// the day is calculated from sunrise to sunset.
445    #[must_use]
446    pub fn mincha_gedola_baal_hatanya(&self) -> Option<DateTime<Tz>> {
447        self.mincha_gedola_mga(&Degrees(1.583))
448    }
449
450    /// Returns the later of
451    /// [`mincha_gedola_baal_hatanya`](ComplexZmanimCalendar::mincha_gedola_baal_hatanya)
452    /// and
453    /// [`mincha_gedola_30_minutes`](ComplexZmanimCalendar::mincha_gedola_30_minutes)
454    /// . In the winter when 1/2 of a
455    /// [*Baal Hatanya shaah
456    /// zmanis*](ComplexZmanimCalendar::shaah_zmanis_baal_hatanya)
457    /// is less than 30 minutes
458    /// [`mincha_gedola_30_minutes`](ComplexZmanimCalendar::mincha_gedola_30_minutes)
459    /// will be returned, otherwise
460    /// [`mincha_gedola_baal_hatanya`](ComplexZmanimCalendar::mincha_gedola_baal_hatanya)
461    ///  will be returned
462    #[must_use]
463    pub fn mincha_gedola_baal_hatanya_greater_than_30_minutes(&self) -> Option<DateTime<Tz>> {
464        let mg_30 = self.mincha_gedola_30_minutes()?;
465        let mg_bht = self.mincha_gedola_baal_hatanya()?;
466        Some(if mg_30 > mg_bht { mg_30 } else { mg_bht })
467    }
468
469    /// Returns the *Baal Hatanya*'s *mincha ketana*. This is the
470    /// preferred earliest time to pray *mincha* in the opinion of the *Rambam*
471    /// and others. For more information on this see the documentation on
472    /// *mincha gedola*. This is calculated as 9.5 of the [*Baal Hatanya*'s
473    /// temporal hours](ComplexZmanimCalendar::shaah_zmanis_baal_hatanya) after
474    /// [*hanetz amiti*](ComplexZmanimCalendar::hanetz_amiti_baal_hatanya)
475    /// (sunrise). This calculation is calculated based on the opinion of
476    /// the *Baal Hatanya* that the day is calculated from sunrise to
477    /// sunset.
478    #[must_use]
479    pub fn mincha_ketana_baal_hatanya(&self) -> Option<DateTime<Tz>> {
480        self.mincha_ketana_mga(&Degrees(1.583))
481    }
482
483    /// Returns the *Baal Hatanya*'s *plag hamincha*. This is
484    /// calculated as 10.75 of the [*Baal Hatanya*'s temporal
485    /// hours](ComplexZmanimCalendar::shaah_zmanis_baal_hatanya) after *hanetz
486    /// amiti* (sunrise). This calculation is calculated based on the
487    /// opinion of the *Baal Hatanya* that the day is calculated from
488    /// sunrise to sunset.
489    #[must_use]
490    pub fn plag_baal_hatanya(&self) -> Option<DateTime<Tz>> {
491        self.plag_mga(&Degrees(1.583))
492    }
493
494    /// Returns *tzais* (nightfall) when the sun is 6&deg; below
495    /// the western geometric horizon (90&deg;) after sunset. This calculation
496    /// is based on the position of the sun 24 minutes after sunset in Jerusalem
497    /// around the equinox / equilux, which is 6&deg; below geometric zenith.
498    #[must_use]
499    pub fn tzais_baal_hatanya(&self) -> Option<DateTime<Tz>> {
500        self.tzais(&Degrees(6.0))
501    }
502
503    // Rav Moshe Feinstein
504    /// Returns fixed local *chatzos*. See
505    /// [`zmanim_calculator::fixed_local_chatzos`] for more details
506    #[must_use]
507    pub fn fixed_local_chatzos(&self) -> Option<DateTime<Tz>> {
508        zmanim_calculator::fixed_local_chatzos(&self.date, &self.geo_location)
509    }
510
511    /// Returns Rav Moshe Feinstein's opinion of the calculation of
512    /// *sof zman krias shema* (latest time to recite *Shema* in the morning)
513    /// according to the opinion of the *Magen Avraham* (MGA) that the day is
514    /// calculated from dawn to nightfall, but calculated using the first half
515    /// of the day only. The half a day starts at *alos* defined as 18&deg; and
516    /// ends at fixed local *chatzos*. *Sof Zman Shema* is 3 *shaos
517    /// zmaniyos* (solar hours) after *alos* or half of this half-day.
518    #[must_use]
519    pub fn sof_zman_shema_mga_18_degrees_to_fixed_local_chatzos(&self) -> Option<DateTime<Tz>> {
520        let alos = self.alos_18_degrees()?;
521        let offset = (self.fixed_local_chatzos()? - alos) / 2;
522        Some(alos + offset)
523    }
524
525    /// Returns Rav Moshe Feinstein's opinion of the calculation of
526    /// *sof zman krias shema* (latest time to recite *Shema* in the morning)
527    /// according to the opinion of the *Magen Avraham* (MGA) that the day is
528    /// calculated from dawn to nightfall, but calculated using the first half
529    /// of the day only. The half a day starts at *alos* defined as 16.1&deg;
530    /// and ends at fixed local *chatzos*. *Sof Zman Shema* is 3 *shaos
531    /// zmaniyos* (solar hours) after this *alos* or half of this half-day.
532    #[must_use]
533    pub fn sof_zman_shema_mga_16_1_degrees_to_fixed_local_chatzos(&self) -> Option<DateTime<Tz>> {
534        let alos = self.alos_16_1_degrees()?;
535        let offset = (self.fixed_local_chatzos()? - alos) / 2;
536        Some(alos + offset)
537    }
538
539    /// Returns Rav Moshe Feinstein's opinion of the calculation of
540    /// *sof zman krias shema* (latest time to recite *Shema* in the morning)
541    /// according to the opinion of the *Magen Avraham* (MGA) that the day is
542    /// calculated from dawn to nightfall, but calculated using the first half
543    /// of the day only. The half a day starts at *alos* defined as 90 minutes
544    /// before sunrise and ends at fixed local *chatzos*. *Sof Zman Shema* is 3
545    /// *shaos zmaniyos* (solar hours) after this *alos* or half of this
546    /// half-day.
547    #[must_use]
548    pub fn sof_zman_shema_mga_90_minutes_to_fixed_local_chatzos(&self) -> Option<DateTime<Tz>> {
549        let alos = self.alos_90_minutes()?;
550        let offset = (self.fixed_local_chatzos()? - alos) / 2;
551        Some(alos + offset)
552    }
553
554    /// Returns Rav Moshe Feinstein's opinion of the calculation of
555    /// *sof zman krias shema* (latest time to recite *Shema* in the morning)
556    /// according to the opinion of the *Magen Avraham* (MGA) that the day is
557    /// calculated from dawn to nightfall, but calculated using the first half
558    /// of the day only. The half a day starts at *alos* defined as 72 minutes
559    /// before sunrise and ends at fixed local *chatzos*. *Sof Zman Shema* is 3
560    /// *shaos zmaniyos* (solar hours) after this *alos* or half of this
561    /// half-day.
562    #[must_use]
563    pub fn sof_zman_shema_mga_72_minutes_to_fixed_local_chatzos(&self) -> Option<DateTime<Tz>> {
564        let alos = self.alos_72_minutes()?;
565        let offset = (self.fixed_local_chatzos()? - alos) / 2;
566        Some(alos + offset)
567    }
568
569    /// Returns Rav Moshe Feinstein's opinion of the calculation of
570    /// *sof zman krias shema* (latest time to recite *Shema* in the morning)
571    /// according to the opinion of the GRA that the day is calculated from
572    /// sunrise to sunset, but calculated using the first half of the day only.
573    /// The half a day starts at sunrise and ends at fixed local *chatzos*. *Sof
574    /// zman Shema* is 3 *shaos zmaniyos* (solar hours) after sunrise or half of
575    /// this half-day.
576    #[must_use]
577    pub fn sof_zman_shema_gra_sunrise_to_fixed_local_chatzos(&self) -> Option<DateTime<Tz>> {
578        let alos = self.hanetz()?;
579        let offset = (self.fixed_local_chatzos()? - alos) / 2;
580        Some(alos + offset)
581    }
582
583    /// Returns Rav Moshe Feinstein's opinion of the calculation of
584    /// *sof zman tefila* (the latest time to recite the morning
585    /// prayers) according to the opinion of the GRA that the day is calculated
586    /// from sunrise to sunset, but calculated using the first half of the day
587    /// only. The half a day starts at sunrise and ends at fixed local
588    /// *chatzos*. *Sof zman tefila* is 4 *shaos zmaniyos* (solar hours) after
589    /// sunrise or 2/3 of this half-day.
590    #[must_use]
591    pub fn sof_zman_tefila_gra_sunrise_to_fixed_local_chatzos(&self) -> Option<DateTime<Tz>> {
592        let alos = self.hanetz()?;
593        let offset = ((self.fixed_local_chatzos()? - alos) * 2) / 3;
594        Some(alos + offset)
595    }
596
597    /// Returns Rav Moshe Feinstein's opinion of the calculation of
598    /// mincha gedola, the earliest time one can pray mincha calculated
599    /// according to the GRA that is 30 minutes after fixed local *chatzos*.
600    #[must_use]
601    pub fn mincha_gedola_gra_fixed_local_chatzos_30_minutes(&self) -> Option<DateTime<Tz>> {
602        Some(self.fixed_local_chatzos()? + TimeDelta::minutes(30))
603    }
604
605    /// Returns Rav Moshe Feinstein's opinion of the calculation of
606    /// mincha ketana (the preferred time to recite the mincha prayers according
607    /// to the opinion of the Rambam and others) calculated according to the GRA
608    /// that is 3.5 *shaos zmaniyos* (solar hours) after fixed local *chatzos*.
609    #[must_use]
610    pub fn mincha_ketana_gra_fixed_local_chatzos_to_sunset(&self) -> Option<DateTime<Tz>> {
611        let chatzos = self.fixed_local_chatzos()?;
612        let half_shaah = (self.shkia()? - chatzos) / 12;
613        Some(chatzos + (half_shaah * 7))
614    }
615
616    /// Returns Rav Moshe Feinstein's opinion of the calculation of
617    /// plag hamincha. This method returns plag hamincha calculated according to
618    /// the GRA that the day ends at sunset and is 4.75 *shaos zmaniyos* (solar
619    /// hours) after fixed local *chatzos*.
620    #[must_use]
621    pub fn plag_gra_fixed_local_chatzos_to_sunset(&self) -> Option<DateTime<Tz>> {
622        let chatzos = self.fixed_local_chatzos()?;
623        // (19/24) == (4.75/6)
624        let quarter_shaah = (self.shkia()? - chatzos) / 24;
625        Some(chatzos + (quarter_shaah * 19))
626    }
627
628    /// Method to return *tzais* (dusk) calculated as 50 minutes after
629    /// sunset. This method returns
630    /// *tzais* (nightfall) based on the opinion of Rabbi Moshe Feinstein
631    /// for the New York area. This time should not be used for latitudes
632    /// other than ones similar to the latitude of the NY area.
633    #[must_use]
634    pub fn tzais_50_minutes(&self) -> Option<DateTime<Tz>> {
635        self.tzais(&Minutes(50.0))
636    }
637
638    // Ahavat Shalom
639    /// Returns the time of *mincha gedola* based on the opinion of
640    /// Rabbi Yaakov Moshe Hillel as published in the luach of the Bais Horaah
641    /// of Yeshivat Chevrat Ahavat Shalom that *mincha gedola* is calculated as
642    /// half a *shaah zmanis* after *chatzos* with *shaos zmaniyos* calculated
643    /// based on a day starting 72 minutes before sunrise (alos 16.1&deg;) and
644    /// ending 13.5 minutes after sunset (*tzais* 3.7&deg;). *Mincha gedola* is
645    /// the earliest time to pray *mincha*. The later of this time or 30
646    /// clock minutes after *chatzos* is returned. See
647    /// [`mincha_gedola_gra_greater_than_30_minutes`](ComplexZmanimCalendar::mincha_gedola_gra_greater_than_30_minutes)
648    /// (though that calculation is based on *mincha gedola* GRA). For more
649    /// information about *mincha gedola* see the documentation on [*mincha
650    /// gedola*](zmanim_calculator::mincha_gedola).
651    #[must_use]
652    pub fn mincha_gedola_ahavat_shalom(&self) -> Option<DateTime<Tz>> {
653        let mg_as = self.chatzos()? + (self.shaah_zmanis_alos_16_1_to_tzais_3_7()? / 2);
654        let mg_30 = self.mincha_gedola_30_minutes()?;
655        Some(if mg_30 > mg_as { mg_30 } else { mg_as })
656    }
657
658    /// Returns the time of *mincha ketana* based on the opinion of
659    /// Rabbi Yaakov Moshe Hillel as published in the luach of the Bais Horaah
660    /// of Yeshivat Chevrat Ahavat Shalom that *mincha ketana* is calculated as
661    /// 2.5 *shaos zmaniyos* before *tzais* 3.8&deg; with *shaos zmaniyos*
662    /// calculated based on a day starting at *alos* 16.1&deg; and ending at
663    /// *tzais* 3.8&deg;. *Mincha ketana* is the preferred earliest time to
664    /// pray *mincha* according to the opinion of the *Rambam* and others.
665    /// For more information on this see the documentation on [*mincha
666    /// gedola*](zmanim_calculator::mincha_gedola).
667    #[must_use]
668    pub fn mincha_ketana_ahavat_shalom(&self) -> Option<DateTime<Tz>> {
669        Some(zmanim_calculator::mincha_ketana(
670            &self.alos_16_1_degrees()?,
671            &self.tzais_geonim_3_8_degrees()?,
672        ))
673    }
674
675    /// Returns the time of *plag hamincha* based on the opinion of
676    /// Rabbi Yaakov Moshe Hillel as published in the luach of the Bais Horaah
677    /// of Yeshivat Chevrat Ahavat Shalom that that *plag hamincha* is
678    /// calculated as 1.25 *shaos zmaniyos* before *tzais* 3.8&deg; with *shaos
679    /// zmaniyos* calculated based on a day starting at *alos* 16.1&deg; and
680    /// ending at *tzais* 3.8&deg;.
681    #[must_use]
682    pub fn plag_ahavat_shalom(&self) -> Option<DateTime<Tz>> {
683        Some(zmanim_calculator::plag_hamincha(
684            &self.alos_16_1_degrees()?,
685            &self.tzais_geonim_3_8_degrees()?,
686        ))
687    }
688
689    /// Returns a *shaah zmanis* (temporal hour) used by some *zmanim*
690    /// according to the opinion of Rabbi Yaakov Moshe Hillel as published in
691    /// the luach of the Bais Horaah of Yeshivat Chevrat Ahavat Shalom that is
692    /// based on a day starting 72 minutes before sunrise in degrees (*alos*
693    /// 16.1&deg;) and ending 14 minutes after sunset in degrees (*tzais*
694    /// 3.8&deg;). This day is split into 12 equal parts with each part
695    /// being a *shaah zmanis*. Note that with this system, *chatzos*
696    /// (midday) will not be the point that the sun is halfway across the
697    /// sky. These *shaos zmaniyos* are used for *Mincha Ketana* and *Plag
698    /// Hamincha*. The 14 minutes are based on 3/4 of an 18 minute *mil*,
699    /// with half a minute added for Rav Yosi.
700    #[must_use]
701    pub fn shaah_zmanis_alos_16_1_to_tzais_3_8(&self) -> Option<TimeDelta> {
702        Some(zmanim_calculator::shaah_zmanis(
703            &self.alos_16_1_degrees()?,
704            &self.tzais_geonim_3_8_degrees()?,
705        ))
706    }
707
708    /// Returns a *shaah zmanis* (temporal hour) used by some *zmanim*
709    /// according to the opinion of Rabbi Yaakov Moshe Hillel as published in
710    /// the luach of the Bais Horaah of Yeshivat Chevrat Ahavat Shalom that is
711    /// based on a day starting 72 minutes before sunrise in degrees (*alos*
712    /// 16.1&deg;) and ending 13.5 minutes after sunset in degrees (*tzais*
713    /// 3.7&deg;). This day is split into 12 equal parts with each part
714    /// being a *shaah zmanis*. Note that with this system, *chatzos*
715    /// (midday) will not be the point that the sun is halfway across the
716    /// sky. These *shaos zmaniyos* are used for *mincha gedola* calculation.
717    #[must_use]
718    pub fn shaah_zmanis_alos_16_1_to_tzais_3_7(&self) -> Option<TimeDelta> {
719        Some(zmanim_calculator::shaah_zmanis(
720            &self.alos_16_1_degrees()?,
721            &self.tzais_geonim_3_7_degrees()?,
722        ))
723    }
724
725    // Ateret Torah
726    /// Returns the latest *zman krias shema* (time to recite
727    /// *Shema* in the morning) based on the calculation of *Chacham* Yosef
728    /// Harari-Raful of Yeshivat Ateret Torah, that the day starts 1/10th of the
729    /// day before sunrise and is usually calculated as ending 40 minutes after
730    /// sunset. *Shaos zmaniyos* are calculated based on this day and added to
731    /// *alos*to reach this time. This time is 3 *shaos zmaniyos* (temporal
732    /// hours) after *alos*72 zmaniyos. Note: Based on this calculation
733    /// *chatzos* will not be at midday.
734    #[must_use]
735    pub fn sof_zman_shema_ateret_torah(&self) -> Option<DateTime<Tz>> {
736        Some(zmanim_calculator::sof_zman_shema(
737            &self.alos_72_minutes_zmanis()?,
738            &self.tzais_ateret_torah()?,
739        ))
740    }
741
742    /// Returns the latest *zman tefila* (time to recite the morning
743    /// prayers) based on the calculation of *Chacham* Yosef Harari-Raful of
744    /// Yeshivat Ateret Torah, that the day starts 1/10th of the day before
745    /// sunrise and is usually calculated as ending 40 minutes after sunset.
746    /// *Shaos zmaniyos* are calculated based on this day and added to *alos*to
747    /// reach this time. This time is 4 * *shaos zmaniyos* (temporal hours)
748    /// after *alos*72 *zmaniyos*. Note: Based on this calculation *chatzos*
749    /// will not be at midday.
750    #[must_use]
751    pub fn sof_zman_tefila_ateret_torah(&self) -> Option<DateTime<Tz>> {
752        Some(zmanim_calculator::sof_zman_tefila(
753            &self.alos_72_minutes_zmanis()?,
754            &self.tzais_ateret_torah()?,
755        ))
756    }
757
758    /// Returns the time of *mincha gedola* based on the calculation of
759    /// *Chacham* Yosef Harari-Raful of Yeshivat Ateret Torah, that the day
760    /// starts 1/10th of the day before sunrise and is usually calculated as
761    /// ending 40 minutes after sunset. The *Rambam* is of the opinion that it
762    /// is better to delay *mincha* until *mincha ketana* while the Ra"sh, Tur,
763    /// GRA and others are of the opinion that mincha can be prayed lechatchila
764    /// starting at mincha gedola. For more information on this see the
765    /// documentation on [*mincha gedola*](zmanim_calculator::mincha_gedola).
766    /// This is calculated as 6.5 solar hours after *alos*. The calculation used
767    /// is 6.5 * [`ComplexZmanimCalendar::shaah_zmanis_ateret_torah`] after
768    /// *alos*.
769    #[must_use]
770    pub fn mincha_gedola_ateret_torah(&self) -> Option<DateTime<Tz>> {
771        Some(zmanim_calculator::mincha_gedola(
772            &self.alos_72_minutes_zmanis()?,
773            &self.tzais_ateret_torah()?,
774        ))
775    }
776
777    /// Returns the time of *mincha ketana* based on the calculation of
778    /// *Chacham* Yosef Harari-Raful of Yeshivat Ateret Torah, that the day
779    /// starts 1/10th of the day before sunrise and is usually calculated as
780    /// ending 40 minutes after sunset. This is the preferred earliest time to
781    /// pray *mincha* according to the opinion of the *Rambam* and others. For
782    /// more information on this see the documentation on [*mincha
783    /// ketana*](zmanim_calculator::mincha_ketana). This is calculated as 9.5
784    /// solar hours after *alos*. The calculation used is 9.5 *
785    /// [`ComplexZmanimCalendar::shaah_zmanis_ateret_torah`] after *alos*.
786    #[must_use]
787    pub fn mincha_ketana_ateret_torah(&self) -> Option<DateTime<Tz>> {
788        Some(zmanim_calculator::mincha_ketana(
789            &self.alos_72_minutes_zmanis()?,
790            &self.tzais_ateret_torah()?,
791        ))
792    }
793
794    /// Returns the time of *plag hamincha* based on the calculation
795    /// of *Chacham* Yosef Harari-Raful of Yeshivat Ateret Torah, that the day
796    /// starts 1/10th of the day before sunrise and is usually calculated as
797    /// ending 40 minutes after sunset. *Shaos zmaniyos* are calculated based on
798    /// this day and added to *alos* to reach this time. This time is 10.75
799    /// *shaos zmaniyos* (temporal hours) after dawn.
800    #[must_use]
801    pub fn plag_ateret_torah(&self) -> Option<DateTime<Tz>> {
802        Some(zmanim_calculator::plag_hamincha(
803            &self.alos_72_minutes_zmanis()?,
804            &self.tzais_ateret_torah()?,
805        ))
806    }
807
808    /// Returns *tzais* calculated as 40 minutes after sunset. Please note that
809    /// *Chacham* Yosef Harari-Raful of Yeshivat Ateret Torah who uses this
810    /// time, does so only for calculating various other zmanei hayom such as
811    /// *Sof Zman Krias Shema* and *Plag Hamincha*. His calendars do not publish
812    /// a *zman* for *Tzais*. It should also be noted that *Chacham*
813    /// Harari-Raful provided a 25 minute *zman* for Israel. This API uses
814    /// 40 minutes year round in any place on the globe.
815    #[must_use]
816    pub fn tzais_ateret_torah(&self) -> Option<DateTime<Tz>> {
817        self.tzais(&Minutes(40.0))
818    }
819
820    /// Returns a shaah zmanis (temporal hour) according to the opinion
821    /// of the *Chacham* Yosef Harari-Raful of Yeshivat Ateret Torah calculated
822    /// with *alos* being 1/10th of sunrise to sunset day, or 72 minutes
823    /// *zmaniyos* of such a day before sunrise, and *tzais* is usually
824    /// calculated as 40 minutes after sunset. This day is split into 12
825    /// equal parts with each part being a shaah zmanis. Note that with this
826    /// system, *chatzos* (midday) will not be the point that the sun is
827    /// halfway across the sky.
828    #[must_use]
829    pub fn shaah_zmanis_ateret_torah(&self) -> Option<TimeDelta> {
830        Some(zmanim_calculator::shaah_zmanis(
831            &self.alos_72_minutes_zmanis()?,
832            &self.tzais_ateret_torah()?,
833        ))
834    }
835
836    // Shach
837    /// Returns the latest *zman krias shema* (time to recite *Shema* in the
838    /// morning) calculated as 3 hours (regular clock hours and not *shaos
839    /// zmaniyos*) before *chatzos*. Generally known as part of the "Komarno"
840    /// *zmanim* after Rav Yitzchak Eizik of Komarno, a proponent of this
841    /// calculation, it actually predates him a lot. It is the opinion of the
842    /// *Shach* in the *Nekudas Hakesef* (*Yoreh Deah* 184), Rav Moshe Lifshitz
843    /// in his commentary *Lechem Mishneh* on *Brachos* 1:2. It is next brought
844    /// down about 100 years later by the *Yaavetz* (in his *siddur*, *Mor
845    /// Uktziah Orach Chaim* 1, *Lechem Shamayim*, *Brachos* 1:2 and *She'elos
846    /// Yaavetz* vol. 1 no. 40), Rav Yitzchak Eizik of Komarno in the *Ma'aseh
847    /// Oreg* on *Mishnayos Brachos* 11:2, *Shevus Yaakov*, *Chasan Sofer* and
848    /// others. See *Yisrael Vehazmanim* vol. 1 7:3, page 55 - 62
849    #[must_use]
850    pub fn sof_zman_shema_3_hrs_before_chatzos(&self) -> Option<DateTime<Tz>> {
851        Some(self.chatzos()? - TimeDelta::hours(3))
852    }
853
854    /// Returns the latest *zman* tefila (time to recite the morning prayers)
855    /// calculated as 2 hours before *chatzos*. This is based on the opinions
856    /// that calculate sof *zman* krias shema as [3 hours before
857    /// *chatzos*](ComplexZmanimCalendar::sof_zman_shema_3_hrs_before_chatzos).
858    #[must_use]
859    pub fn sof_zman_tefila_2_hrs_before_chatzos(&self) -> Option<DateTime<Tz>> {
860        Some(self.chatzos()? - TimeDelta::hours(2))
861    }
862
863    zmanim_for_offset!(
864        _16_1_degrees,
865        |_| Some(Degrees(16.1)),
866        [
867            alos => alos_degrees_basedon_doc!(16.1, 72),
868            tzais => tzais_degrees_basedon_doc!(16.1, 72),
869            shaah_zmanis_mga => shaah_mga_degrees_basedon_doc!(16.1, 72),
870            sof_zman_shema_mga => szks_mga_degrees_doc!(16.1),
871            sof_zman_tefila_mga => szt_mga_degrees_doc!(16.1),
872            sof_zman_biur_chametz_mga => sz_biur_chametz_mga_degrees_doc!(16.1),
873            mincha_gedola_mga => mg_mga_degrees_doc!(16.1),
874            samuch_lemincha_ketana_mga => slmk_mga_degrees_doc!(16.1),
875            mincha_ketana_mga => mk_mga_degrees_doc!(16.1),
876            plag_mga => plag_mga_degrees_lechumra_doc!(16.1),
877        ]
878    );
879    // *alos* 16.1 degrees to sunset
880    /// Returns the latest *zman krias shema* (time to recite
881    /// *Shema* in the morning) based on the opinion that the day starts at
882    /// *alos* 16.1&deg; and ends at sea level sunset (no adjustment for
883    /// elevation is made). This is the opinion of the *Chidushei UKlalos
884    /// HaRazah* and the *Menora Hatehora* as mentioned by *Yisrael
885    /// Vehazmanim* vol 1, sec. 7, ch. 3 no. 16. Three *shaos zmaniyos* are
886    /// calculated based on this day and added to *alos* to reach this time.
887    /// This time is 3 *shaos zmaniyos* (solar hours) after dawn based on
888    /// the opinion that the day is calculated from a *alos* 16.1&deg; to
889    /// sea level sunset.
890    #[must_use]
891    pub fn sof_zman_shema_alos_16_1_degrees_to_sunset(&self) -> Option<DateTime<Tz>> {
892        Some(zmanim_calculator::sof_zman_shema(
893            &self.alos_16_1_degrees()?,
894            &self.sea_level_sunset()?,
895        ))
896    }
897
898    // seems like this method was removed from KJ
899    /// This method should be used *lechumra* only and returns the time of *plag
900    /// hamincha* based on the opinion that the day starts at *alos* 16.1&deg;
901    /// and ends at sunset.
902    /// 
903    /// 10.75 *shaos zmaniyos* are calculated based on
904    /// this day and added to *alos*to reach this time. This time is 10.75
905    /// *shaos zmaniyos* (temporal hours) after dawn based on the opinion
906    /// that the day is calculated from a dawn of 16.1 degrees before
907    /// sunrise to sunset. This returns the time of 10.75 * the calculated
908    /// *shaah zmanis* after dawn. Since plag by this calculation can occur
909    /// after sunset, it should only be used *lechumra*.
910    #[must_use]
911    pub fn plag_alos_16_1_degrees_to_sunset(&self) -> Option<DateTime<Tz>> {
912        Some(zmanim_calculator::plag_hamincha(
913            &self.alos_16_1_degrees()?,
914            &self.shkia()?,
915        ))
916    }
917
918    // 16.1 degrees to *tzais* geonim 7.083 degrees
919    /// Returns the latest *zman krias shema* (time to recite
920    /// *Shema* in the morning) based on the opinion that the day starts at
921    /// *alos* 16.1&deg; and ends at *tzais* 7.083&deg;. 3 *shaos zmaniyos*
922    /// are calculated based on this day and added to *alos*to reach this
923    /// time. This time is 3 *shaos zmaniyos* (temporal hours) after alos
924    /// 16.1&deg; based on the opinion that the day is calculated from a
925    /// *alos* 16.1&deg; to *tzais* 7.083&deg;.
926    #[must_use]
927    pub fn sof_zman_shema_alos_16_1_degrees_to_tzais_geonim_7_083_degrees(
928        &self,
929    ) -> Option<DateTime<Tz>> {
930        Some(zmanim_calculator::sof_zman_shema(
931            &self.alos_16_1_degrees()?,
932            &self.tzais_geonim_7_083_degrees()?,
933        ))
934    }
935
936    /// Returns the time of *plag hamincha* based on the opinion
937    /// that the day starts at *alos* 16.1&deg; and ends at *tzais*
938    /// 7.083&deg;. 10.75 *shaos zmaniyos* are calculated based on this day
939    /// and added to *alos* to reach this time. This time is 10.75 *shaos
940    /// zmaniyos* (temporal hours) after dawn based on the opinion that the
941    /// day is calculated from a dawn of 16.1 degrees before sunrise to
942    /// *tzais* 7.083&deg;. This returns the time of 10.75 * the calculated
943    /// *shaah zmanis* after dawn.
944    #[must_use]
945    pub fn plag_alos_16_1_degrees_to_tzais_geonim_7_083_degrees(&self) -> Option<DateTime<Tz>> {
946        Some(zmanim_calculator::plag_hamincha(
947            &self.alos_16_1_degrees()?,
948            &self.tzais_geonim_7_083_degrees()?,
949        ))
950    }
951
952    zmanim_for_offset!(
953        _18_degrees,
954        |_| Some(Degrees(18.0)),
955        [
956            alos => alos_degrees_doc!(18),
957            tzais => tzais_degrees_doc!(18),
958            shaah_zmanis_mga => shaah_mga_degrees_doc!(18),
959            sof_zman_shema_mga => szks_mga_degrees_doc!(18),
960            sof_zman_tefila_mga => szt_mga_degrees_doc!(18),
961            plag_mga => plag_mga_degrees_lechumra_doc!(18),
962        ]
963    );
964
965    // 19 degrees
966    /// Returns *alos* (dawn) calculated when the sun is 19&deg;
967    /// below the eastern geometric horizon before sunrise. This is the
968    /// *Rambam*'s *alos* according to Rabbi Moshe Kosower's *Maaglei Tzedek*,
969    /// page 88, *Ayeles Hashachar* Vol. I, page 12, *Yom Valayla Shel Torah*,
970    /// Ch. 34, p. 222 and Rabbi Yaakov Shakow's *Luach Ikvei Hayom*.
971    #[must_use]
972    pub fn alos_19_degrees(&self) -> Option<DateTime<Tz>> {
973        self.alos(&Degrees(19.0))
974    }
975
976    zmanim_for_offset!(
977        _19_8_degrees,
978        |_| Some(Degrees(19.8)),
979        [
980            alos => alos_degrees_basedon_doc!(19.8, 90),
981            tzais => tzais_degrees_basedon_doc!(19.8, 90),
982            shaah_zmanis_mga => shaah_mga_degrees_basedon_doc!(19.8, 90),
983            sof_zman_shema_mga => szks_mga_degrees_doc!(19.8),
984            sof_zman_tefila_mga => szt_mga_degrees_doc!(19.8),
985            plag_mga => plag_mga_degrees_lechumra_doc!(19.8),
986        ]
987    );
988
989    zmanim_for_offset!(
990        _26_degrees,
991        |_| Some(Degrees(26.0)),
992        [
993            alos => alos_degrees_basedon_lechumra_doc!(26, 120),
994            tzais => tzais_degrees_basedon_doc!(26, 120),
995            shaah_zmanis_mga => shaah_mga_degrees_lechumra_basedon_doc!(26, 120),
996            plag_mga => plag_mga_degrees_lechumra_doc!(26),
997        ]
998    );
999
1000    zmanim_for_offset!(
1001        _60_minutes,
1002        |_| Some(Minutes(60.0)),
1003        [
1004            alos => "Returns *alos* (dawn) calculated as 60 minutes before sunrise. This is the time to walk the distance of 4 *mil* at 15 minutes a *mil*. This seems to be the opinion of the *Chavas Yair* in the *Mekor Chaim, Orach Chaim* Ch. 90, though the *Mekor Chaim* in Ch. 58 and in the *Chut Hashani* Ch. 97 states that a person walks 3 and a 1/3 *mil* in an hour, or an 18-minute *mil*. Also see the *Divrei Malkiel* Vol. 4, Ch. 20, page 34) who mentions the 15 minute *mil lechumra* by baking *matzos*. Also see the *Maharik* Ch. 173 where the questioner quoting the *Ra'avan* is of the opinion that the time to walk a *mil* is 15 minutes (5 *mil* in a little over an hour). There are many who believe that there is a *ta'us sofer* (scribeal error) in the *Ra'avan*, and it should 4 *mil* in a little over an hour, or an 18-minute *mil*. Time based offset calculations are based on the opinion of the *Rishonim* who stated that the time of the *neshef* (time between dawn and sunrise) does not vary by the time of year or location but purely depends on the time it takes to walk the distance of 4 *mil*.",
1005            tzais => "Returns *tzais hakochavim* (nightfall) based on the opinion of the *Chavas Yair* and *Divrei Malkiel* that the time to walk the distance of a mil is 15 minutes, for a total of 60 minutes for 4 *mil* after sunset. See detailed documentation explaining the 60 minute concept at [alos_60_minutes](ComplexZmanimCalendar::alos_60_minutes).",
1006            shaah_zmanis_mga => shaah_mga_minutes_doc!(60),
1007            plag_mga => plag_mga_minutes_doc!(60),
1008        ]
1009    );
1010
1011    zmanim_for_offset!(
1012        _72_minutes,
1013        |_| Some(Minutes(72.0)),
1014        [
1015            alos => alos_minutes_basedon_doc!(72, 18),
1016            tzais => "Returns *tzais hakochavim* (nightfall) based on the opinion of *Rabbeinu Tam* that *tzais hakochavim* is calculated as 72 minutes after sunset, the time it takes to walk 4 *mil* at 18 minutes a mil. According to the *Machtzis Hashekel* in *Orach Chaim* 235:3, the *Pri Megadim* in *Orach Chaim* 261:2 (see the *Biur Halacha*) and others (see *Hazmanim Bahalacha* 17:3 and 17:5) the 72 minutes are standard clock minutes any time of the year in any location.",
1017            shaah_zmanis_mga => shaah_mga_minutes_doc!(72),
1018            sof_zman_shema_mga => szks_mga_minutes_doc!(72),
1019            sof_zman_tefila_mga => szt_mga_minutes_doc!(72),
1020            sof_zman_biur_chametz_mga => sz_biur_chametz_mga_minutes_doc!(72),
1021            mincha_gedola_mga => mg_mga_minutes_doc!(72),
1022            samuch_lemincha_ketana_mga => slmk_mga_minutes_doc!(72),
1023            mincha_ketana_mga => mk_mga_minutes_doc!(72),
1024            plag_mga => plag_mga_minutes_lechumra_doc!(72),
1025        ]
1026    );
1027
1028    zmanim_for_offset!(
1029        _72_minutes_zmanis,
1030        |this: &ComplexZmanimCalendar| {
1031            Some(MinutesZmaniyos {
1032                minutes_zmaniyos: 72.0,
1033                shaah_zmanis: this.shaah_zmanis_gra()?,
1034            })
1035        },
1036        [
1037            alos => concat!(
1038                alos_minutes_zmanis_basedon_doc!(72, 18, "1/10th"),
1039                "\nThis calculation is used in the calendars published by the Hisachdus Harabanim D'Artzos Habris Ve'Canada."
1040            ),
1041            tzais => "Returns *tzais hakochavim* (nightfall) calculated as 72 minutes *zmaniyos*, or 1/10th of the day after sunset. This is the way that the *Minchas Cohen* in *Ma'amar* 2:4 calculates *Rebbeinu Tam*'s time of *tzeis*. It should be noted that this calculation results in the shortest time from sunset to *tzais* being during the winter solstice, the longest at the summer solstice and 72 clock minutes at the equinox. This does not match reality, since there is no direct relationship between the length of the day and twilight. The shortest twilight is during the equinox, the longest is during the summer solstice, and in the winter with the shortest daylight, the twilight period is longer than during the equinoxes.",
1042            shaah_zmanis_mga => shaah_mga_minutes_zmanis_doc!(72, "1/10th"),
1043            sof_zman_shema_mga => szks_mga_minutes_zmanis_doc!(72, "1/10th"),
1044            sof_zman_tefila_mga => szt_mga_minutes_zmanis_doc!(72, "1/10th"),
1045            sof_zman_biur_chametz_mga => sz_biur_chametz_mga_minutes_zmanis_doc!(72, "1/10th"),
1046            plag_mga => plag_mga_minutes_zmanis_lechumra_doc!(72, "1/10th"),
1047        ]
1048    );
1049
1050    zmanim_for_offset!(
1051        _90_minutes,
1052        |_| Some(Minutes(90.0)),
1053        [
1054            alos => alos_minutes_basedon_doc!(90, 22.5),
1055            tzais => "Returns *tzais hakochavim* (dusk) calculated as 90 minutes after sunset. This method returns *tzais* based on the opinion of the *Magen Avraham* that the time to walk the distance of a *mil* according to the *Rambam*'s opinion is 18 minutes, for a total of 90 minutes based on the opinion of Ula who calculated *tzais* as 5 *mil* after *shkiah* (sunset). A similar calculation [tzais_19_8_degrees](ComplexZmanimCalendar::tzais_19_8_degrees) uses solar position calculations based on this time.",
1056            shaah_zmanis_mga => shaah_mga_minutes_doc!(90),
1057            sof_zman_shema_mga => szks_mga_minutes_doc!(90),
1058            sof_zman_tefila_mga => szt_mga_minutes_doc!(90),
1059            plag_mga => plag_mga_minutes_lechumra_doc!(90),
1060        ]
1061    );
1062
1063    zmanim_for_offset!(
1064        _90_minutes_zmanis,
1065        |this: &ComplexZmanimCalendar| {
1066            Some(MinutesZmaniyos {
1067                minutes_zmaniyos: 90.0,
1068                shaah_zmanis: this.shaah_zmanis_gra()?,
1069            })
1070        },
1071        [
1072            alos => alos_minutes_zmanis_basedon_doc!(90, 22.5, "1/8th"),
1073            tzais => concat!(
1074                tzais_minutes_zmanis_basedon_doc!(90, 22.5, "1/8th"),
1075                " This time is known in Yiddish as the *achtel* (an eighth) *zman*."
1076            ),
1077            shaah_zmanis_mga => shaah_mga_minutes_zmanis_doc!(90, "1/8th"),
1078            sof_zman_shema_mga => szks_mga_minutes_zmanis_doc!(90, "1/8th"),
1079            sof_zman_tefila_mga => szt_mga_minutes_zmanis_doc!(90, "1/8th"),
1080            plag_mga => plag_mga_minutes_zmanis_lechumra_doc!(90, "1/8th"),
1081        ]
1082    );
1083
1084    zmanim_for_offset!(
1085        _96_minutes,
1086        |_| Some(Minutes(96.0)),
1087        [
1088            alos => alos_minutes_basedon_doc!(96, 24),
1089            tzais => tzais_minutes_basedon_doc!(96, 24),
1090            shaah_zmanis_mga => shaah_mga_minutes_doc!(96),
1091            sof_zman_shema_mga => szks_mga_minutes_doc!(96),
1092            sof_zman_tefila_mga => szt_mga_minutes_doc!(96),
1093            plag_mga => plag_mga_minutes_lechumra_doc!(96),
1094        ]
1095    );
1096
1097    zmanim_for_offset!(
1098        _96_minutes_zmanis,
1099        |this: &ComplexZmanimCalendar| {
1100            Some(MinutesZmaniyos {
1101                minutes_zmaniyos: 96.0,
1102                shaah_zmanis: this.shaah_zmanis_gra()?,
1103            })
1104        },
1105        [
1106            alos => alos_minutes_zmanis_basedon_doc!(96, 22.5, "1/7.5th"),
1107            tzais => tzais_minutes_zmanis_basedon_doc!(96, 22.5, "1/7.5th"),
1108            shaah_zmanis_mga => shaah_mga_minutes_zmanis_doc!(96, "1/7.5th"),
1109            sof_zman_shema_mga => szks_mga_minutes_zmanis_doc!(96, "1/7.5th"),
1110            sof_zman_tefila_mga => szt_mga_minutes_zmanis_doc!(96, "1/7.5th"),
1111            plag_mga => plag_mga_minutes_zmanis_lechumra_doc!(96, "1/7.5th"),
1112        ]
1113    );
1114
1115    zmanim_for_offset!(
1116        _120_minutes,
1117        |_| Some(Minutes(120.0)),
1118        [
1119            alos => "This method should be used *lechumra* only and returns *alos* (dawn) calculated using 120 minutes before sea level sunrise (no adjustment for elevation is made) based on the time to walk the distance of 5 *mil* (Ula) at 24 minutes a *mil*. Time based offset calculations for *alos* are based on the* opinion of the Rishonim who stated that the time of the *neshef* (time between dawn and sunrise) does not vary by the time of year or location but purely depends on the time it takes to walk the distance of 5 *mil* (Ula). Since this time is extremely early, it should only be used *lechumra*, such as not eating after this time on a fast day, and **not** as the start time for *mitzvos* that can only be performed during the day.",
1120            tzais => "Returns *tzais hakochavim* (dusk) calculated as 120 minutes after sunset. For information on how this is calculated see the documentation on [alos_120_minutes](ComplexZmanimCalendar::alos_120_minutes).",
1121            shaah_zmanis_mga => shaah_mga_minutes_doc!(120),
1122            sof_zman_shema_mga => szks_mga_minutes_doc!(120),
1123            sof_zman_tefila_mga => szt_mga_minutes_doc!(120),
1124            plag_mga => plag_mga_minutes_lechumra_doc!(120),
1125        ]
1126    );
1127
1128    zmanim_for_offset!(
1129        _120_minutes_zmanis,
1130        |this: &ComplexZmanimCalendar| {
1131            Some(MinutesZmaniyos {
1132                minutes_zmaniyos: 120.0,
1133                shaah_zmanis: this.shaah_zmanis_gra()?,
1134            })
1135        },
1136        [
1137            alos => "This method should be used *lechumra* only and method returns *alos* (dawn) calculated using 120 minutes *zmaniyos* or 1/6th of the day before sunrise. This is based on a 24-minute *mil* so the time for 5 mil is 120 minutes which is 1/6th of a day `(12 * 60) / 6 = 120`. The day is calculated from sunrise to sunset. The actual calculation used is `astronomical_calculator::sunrise(&self.date, &self.geo_location) - (&self.shaah_zmanis_gra()? * 2.0)`. Since this time is extremely early, it should only be used *lechumra*, such as not eating after this time on a fast day, and **not** as the start time for *mitzvos* that can only be performed during the day.",
1138            tzais => "This method should be used *lechumra* only and returns *tzais* (dusk) calculated using 120 minutes *zmaniyos* after sunset. Since the *zman* is extremely late and at a time when the sun is well below the 18&deg; point (scientifically the darkest point) in most places on the globe, it should only be used *lechumra*, such as delaying the start of nighttime mitzvos.",
1139            shaah_zmanis_mga => "Returns a *shaah zmanis* (temporal hour) calculated using a dip of 120 minutes. This calculation divides the day based on the opinion of the *Magen Avraham* (MGA) that the day runs from dawn to dusk. Dawn for this calculation is 120 minutes before sunrise and dusk is 120 minutes after sunset. This day is split into 12 equal parts with each part being a *shaah zmanis*. This is identical to 1/6th of the day from sunrise to sunset. Since *zmanim* that use this method are extremely late or early and at a point when the sky is a long time past the 18&deg; point where the darkest point is reached, *zmanim* that use this should only be used *lechumra* only, such as delaying the start of nighttime *mitzvos*.",
1140            plag_mga => plag_mga_minutes_zmanis_lechumra_doc!(120, "1/6th"),
1141        ]
1142    );
1143
1144    // Other Misheyakir
1145    /// Returns *misheyakir* based on the position of the sun 12.85&deg; below
1146    /// geometric zenith (90&deg;). This is based on the position of the sun
1147    /// slightly later than 57 minutes before sunrise in Jerusalem around the
1148    /// equinox / equilux. This *zman* is mentioned for use ***bish'as
1149    /// hadchak*** in the Birur Halacha Tinyana and Tlisa'ah in Orach Chaim
1150    /// siman 18 as 12.85&deg;. Actual calculations show it to be slightly more
1151    /// than 12.9&deg;, but the Birur Halacha indicates that 12.85&deg; is a
1152    /// slight *chumra* (on a *bedieved* time) VS the 12.9&deg; that 57 minutes
1153    /// calculates as (a difference of about 14 seconds at the equinox/equilux
1154    /// in Jerusalem). The *zman* of 12.9&deg; is also mentioned in the Piskei
1155    /// Tshuvos siman 18, page 190 (where a typo indicates that this is the
1156    /// degree equivalent to 60 minutes before sunrise, when in fact at that
1157    /// point the sun is about 13.5&deg; below the horizon). The 57 minute based
1158    /// time is mentioned by the Minchas Yitzchak vol. 9, siman 9 as 15 minutes
1159    /// before *alos hashachar* (though he is not clear what location he refers
1160    /// to, and does not mention a degree-based conversion). The Kaf Hachaim
1161    /// vol.1 siman 18, no. 18 states that in Yerushalayim 60 fixed minutes are
1162    /// used year round. Calculations show that 60 fixed minutes in Yerushalayim
1163    /// ranges from 13.5&deg; at the spring equinox to 11.5&deg; at the summer
1164    /// solstice. 57 minutes range from 12.9&deg; at the winter equinox to
1165    /// 11&deg; at the summer solstice. Analysis of the difference between
1166    /// 12.85&deg; and 12.9&deg;, shows that the maximum difference occurs at
1167    /// the summer solstice. In Lakewood, NJ at a latitude of 40.096&deg;, the
1168    /// maximum difference throughout the year is 23 seconds. In the winter
1169    /// where there is the greatest need for very early *misheyakir* times, the
1170    /// difference is in the 16 second range. Going north to Montreal at
1171    /// latitude 45.5&deg;, the maximum is 29 seconds and is about 18 seconds in
1172    /// the winter. Moving farther north to the elevation of Vilnius at a
1173    /// latitude of 54.68&deg;, things change. Firstly, around the summer
1174    /// solstice it will not reach that far below the horizon. On the dates that
1175    /// both can be calculated, the maximum difference can be pretty high on one
1176    /// or two days of the year (around Jul 8), with about a week having over a
1177    /// two minute difference between the two. Even at the latitude of Vilna,
1178    /// from Dec - March, the difference is about 22 seconds.
1179    #[must_use]
1180    pub fn misheyakir_12_85_degrees(&self) -> Option<DateTime<Tz>> {
1181        self.alos(&Degrees(12.85))
1182    }
1183
1184    /// Returns *misheyakir* based on the position of the sun when
1185    /// it is 11.5&deg; below geometric zenith (90&deg;). This calculation is
1186    /// used for calculating *misheyakir* according to some opinions. This
1187    /// calculation is based on the position of the sun 52 minutes before
1188    /// sunrise in Jerusalem around the equinox / equilux, which calculates
1189    /// to 11.5&deg; below geometric zenith.
1190    #[must_use]
1191    pub fn misheyakir_11_5_degrees(&self) -> Option<DateTime<Tz>> {
1192        self.alos(&Degrees(11.5))
1193    }
1194
1195    /// Returns *misheyakir* based on the position of the sun when
1196    /// it is 11&deg; below geometric zenith (90&deg;). This calculation is used
1197    /// for calculating *misheyakir* according to some opinions. This
1198    /// calculation is based on the position of the sun 48 minutes before
1199    /// sunrise in Jerusalem around the equinox / equilux, which calculates
1200    /// to 11&deg; below geometric zenith.
1201    #[must_use]
1202    pub fn misheyakir_11_degrees(&self) -> Option<DateTime<Tz>> {
1203        self.alos(&Degrees(11.0))
1204    }
1205
1206    /// Returns *misheyakir* based on the position of the sun when
1207    /// it is 10.2&deg; below geometric zenith (90&deg;). This calculation is
1208    /// used for calculating *misheyakir* according to some opinions. This
1209    /// calculation is based on the position of the sun 45 minutes before
1210    /// sunrise in Jerusalem around the equinox which calculates to 10.2&deg;
1211    /// below geometric zenith.
1212    #[must_use]
1213    pub fn misheyakir_10_2_degrees(&self) -> Option<DateTime<Tz>> {
1214        self.alos(&Degrees(10.2))
1215    }
1216
1217    /// Returns *misheyakir* based on the position of the sun when
1218    /// it is 9.5&deg; below geometric zenith (90&deg;). This calculation is
1219    /// based on Rabbi Dovid Kronglass's Calculation of 45 minutes in
1220    /// Baltimore as mentioned in *Divrei Chachamim* No. 24 brought down by
1221    /// the *Birur Halacha*, *Tinyana*, Ch. 18. This calculates to 9.5&deg;.
1222    /// Also see Rabbi Yaakov Yitzchok Neiman in *Kovetz Eitz Chaim* Vol. 9,
1223    /// p. 202 that the *Vya'an Yosef* did not want to rely on times earlier
1224    /// than 45 minutes in New York. This *zman* is also used in the
1225    /// calendars published by Rabbi Hershel Edelstein. As mentioned in
1226    /// Yisroel Vehazmanim, Rabbi Edelstein who was given the 45 minute
1227    /// *zman* by Rabbi Bick. The calendars published by the *Edot
1228    /// Hamizrach* communities also use this *zman*. This also follows the
1229    /// opinion of Rabbi Shmuel Kamenetsky who provided the time of 36 and
1230    /// 45 minutes, but did not provide a degree-based time. Since this
1231    /// *zman* depends on the level of light, Rabbi Yaakov Shakow presented
1232    /// these degree-based times to Rabbi Shmuel Kamenetsky who agreed to
1233    /// them.
1234    #[must_use]
1235    pub fn misheyakir_9_5_degrees(&self) -> Option<DateTime<Tz>> {
1236        self.alos(&Degrees(9.5))
1237    }
1238
1239    /// Returns *misheyakir* based on the position of the sun when
1240    /// it is 7.65&deg; below geometric zenith (90&deg;). The degrees are based
1241    /// on a 35/36 minute *zman* around the equinox / equilux, when the
1242    /// *neshef* (twilight) is the shortest. This time is based on Rabbi
1243    /// Moshe Feinstein who writes in *Ohr Hachaim* Vol. 4, Ch. 6 that
1244    /// *misheyakir* in New York is 35-40 minutes before sunrise, something
1245    /// that is a drop less than 8&deg;. Rabbi Yisroel Taplin in *Zmanei
1246    /// Yisrael* (page 117) notes that Rabbi Yaakov Kamenetsky stated that
1247    /// it is not less than 36 minutes before sunrise (maybe it is
1248    /// 40 minutes). *Sefer Yisrael Vehazmanim* (p. 7) quotes the *Tamar
1249    /// Yifrach* in the name of the Satmar Rov that one should be stringent
1250    /// not consider *misheyakir* before 36 minutes. This is also the
1251    /// accepted *minhag* in Lakewood that is used in the Yeshiva. This
1252    /// follows the opinion of Rabbi Shmuel Kamenetsky who provided the time
1253    /// of 35/36 minutes, but did not provide a degree-based time. Since
1254    /// this *zman* depends on the level of light, Rabbi Yaakov Shakow
1255    /// presented this degree-based calculations to Rabbi Shmuel Kamenetsky
1256    /// who agreed to them.
1257    #[must_use]
1258    pub fn misheyakir_7_65_degrees(&self) -> Option<DateTime<Tz>> {
1259        self.alos(&Degrees(7.65))
1260    }
1261
1262    // Bein Hashmashos Yereim
1263    /// Returns the beginning of *bein hashmashos* (twilight)
1264    /// according to the Yereim (Rabbi Eliezer of Metz) calculated as 18 minutes
1265    /// or 3/4 of a 24-minute mil before sunset. According to the Yereim, bein
1266    /// hashmashos starts 3/4 of a mil before sunset and *tzais* or nightfall
1267    /// starts at sunset.
1268    #[must_use]
1269    pub fn bein_hashmashos_yereim_18_minutes(&self) -> Option<DateTime<Tz>> {
1270        self.tzais(&Minutes(-18.0))
1271    }
1272
1273    /// Returns the beginning of *bein hashmashos* (twilight)
1274    /// according to the Yereim (Rabbi Eliezer of Metz) calculated as the sun's
1275    /// position 3.05&deg; above the horizon around the equinox / equilux, its
1276    /// position 18 minutes or 3/4 of an 24-minute mil before sunset. According
1277    /// to the Yereim, *bein hashmashos* starts 3/4 of a mil before sunset and
1278    /// *tzais* or nightfall starts at sunset. Note that lechumra (of about 14
1279    /// seconds) a refraction value of 0.5166&deg; as opposed to the traditional
1280    /// 0.566&deg; is used. This is more inline with the actual refraction in
1281    /// Eretz Yisrael and is brought down by Rabbi Yedidya Manet in his
1282    /// Zmanei Halacha Lema'aseh (p. 11). That is the first source that I am
1283    /// aware of that calculates degree-based Yereim zmanim. The 0.5166&deg;
1284    /// refraction is also used by the Luach Itim Lebinah. Calculating the
1285    /// Yereim's *bein hashmashos* using 18-minute based degrees is also
1286    /// suggested in the upcoming 8th edition of the zmanim Kehilchasam. For
1287    /// more details, see the article The Yereim's Bein Hashmashos.
1288    #[must_use]
1289    pub fn bein_hashmashos_yereim_3_05_degrees(&self) -> Option<DateTime<Tz>> {
1290        self.tzais(&Degrees(-3.05))
1291    }
1292
1293    /// Returns the beginning of *bein hashmashos* (twilight)
1294    /// according to the Yereim (Rabbi Eliezer of Metz) calculated as 16.875
1295    /// minutes or 3/4 of a 22.5-minute mil before sunset. According to the
1296    /// Yereim, *bein hashmashos* starts 3/4 of a mil before sunset and *tzais*
1297    /// or nightfall starts at sunset.
1298    #[must_use]
1299    pub fn bein_hashmashos_yereim_16_875_minutes(&self) -> Option<DateTime<Tz>> {
1300        self.tzais(&Minutes(-16.875))
1301    }
1302
1303    /// Returns the beginning of *bein hashmashos* (twilight)
1304    /// according to the Yereim (Rabbi Eliezer of Metz) calculated as the sun's
1305    /// position 2.8&deg; above the horizon around the equinox / equilux, its
1306    /// position 16.875 minutes or 3/4 of an 18-minute mil before sunset.
1307    /// According to the Yereim, *bein hashmashos* starts 3/4 of a mil before
1308    /// sunset and *tzais* or nightfall starts at sunset. Details, including how
1309    /// the degrees were calculated can be seen in the documentation of
1310    /// [`bein_hashmashos_yereim_3_05_degrees`](ComplexZmanimCalendar::bein_hashmashos_yereim_3_05_degrees).
1311    #[must_use]
1312    pub fn bein_hashmashos_yereim_2_8_degrees(&self) -> Option<DateTime<Tz>> {
1313        self.tzais(&Degrees(-2.8))
1314    }
1315
1316    /// Returns the beginning of *bein hashmashos* (twilight)
1317    /// according to the Yereim (Rabbi Eliezer of Metz) calculated as 13.5
1318    /// minutes or 3/4 of an 18-minute mil before sunset. According to the
1319    /// Yereim, *bein hashmashos* starts 3/4 of a mil before sunset and *tzais*
1320    /// or nightfall starts at sunset.
1321    #[must_use]
1322    pub fn bein_hashmashos_yereim_13_5_minutes(&self) -> Option<DateTime<Tz>> {
1323        self.tzais(&Minutes(-13.5))
1324    }
1325
1326    /// Returns the beginning of *bein hashmashos* according to the
1327    /// Yereim (Rabbi Eliezer of Metz) calculated as the sun's position 2.1&deg;
1328    /// above the horizon around the equinox / equilux in Yerushalayim, its
1329    /// position 13.5 minutes or 3/4 of an 18-minute mil before sunset.
1330    /// According to the Yereim, *bein hashmashos* starts 3/4 of a mil before
1331    /// sunset and *tzais* or nightfall starts at sunset. Details, including how
1332    /// the degrees were calculated can be seen in the documentation of
1333    /// [`bein_hashmashos_yereim_3_05_degrees`](ComplexZmanimCalendar::bein_hashmashos_yereim_3_05_degrees).
1334    #[must_use]
1335    pub fn bein_hashmashos_yereim_2_1_degrees(&self) -> Option<DateTime<Tz>> {
1336        self.tzais(&Degrees(-2.1))
1337    }
1338
1339    // Bein Hashmashos Rabeinu Tam
1340    /// Method to return the beginning of *bein hashmashos* of Rabbeinu Tam
1341    /// calculated when the sun is 13.24&deg; below the western geometric
1342    /// horizon (90&deg;) after sunset. This calculation is based on the
1343    /// same calculation of [*bein hashmashos* Rabbeinu Tam
1344    /// 58.5](ComplexZmanimCalendar::bein_hashmashos_rt_58_5_minutes) minutes
1345    /// but uses a degree-based calculation instead of 58.5 exact minutes.
1346    /// This calculation is based on the position of the sun 58.5 minutes
1347    /// after sunset in Jerusalem around the equinox / equilux, which
1348    /// calculates to 13.24&deg; below geometric zenith. NOTE: As per
1349    /// Yisrael Vehazmanim Vol. III page 1028, No. 50, a dip of slightly
1350    /// less than 13&deg; should be used. Calculations show that the proper
1351    /// dip to be 13.2456&deg; (truncated to 13.24 that provides about 1.5
1352    /// second earlier (*lechumra*) time) below the horizon at that time. This
1353    /// makes a difference of 1 minute and 10 seconds in Jerusalem during the
1354    /// Equinox, and 1 minute 29 seconds during the solstice as compared to the
1355    /// proper 13.24&deg; versus 13&deg;. For NY during the solstice, the
1356    /// difference is 1 minute 56 seconds.
1357    #[must_use]
1358    pub fn bein_hashmashos_rt_13_24_degrees(&self) -> Option<DateTime<Tz>> {
1359        self.tzais(&Degrees(13.24))
1360    }
1361
1362    /// Returns the beginning of *bein hashmashos* of Rabbeinu Tam
1363    /// calculated as a 58.5-minute offset after sunset. *bein hashmashos* is
1364    /// 3/4 of a mil before *tzais* or 3 1/4 mil after sunset. With a mil
1365    /// calculated as 18 minutes, 3.25 * 18 = 58.5 minutes.
1366    #[must_use]
1367    pub fn bein_hashmashos_rt_58_5_minutes(&self) -> Option<DateTime<Tz>> {
1368        self.tzais(&Minutes(58.5))
1369    }
1370
1371    /// Returns the beginning of *bein hashmashos* based on the
1372    /// calculation of 13.5 minutes (3/4 of an 18-minute mil) before *shkiah*
1373    /// calculated as 7.083&deg;.
1374    #[must_use]
1375    pub fn bein_hashmashos_rt_13_5_minutes_before_7_083_degrees(&self) -> Option<DateTime<Tz>> {
1376        Some(self.tzais_geonim_7_083_degrees()? - TimeDelta::seconds(810))
1377    }
1378
1379    /// Returns the beginning of *bein hashmashos* of Rabbeinu Tam
1380    /// calculated according to the opinion of the Divrei Yosef (see Yisrael
1381    /// Vehazmanim) calculated 5/18th (27.77%) of the time between alos
1382    /// (calculated as 19.8&deg; before sunrise) and sunrise. This is added to
1383    /// sunset to arrive at the time for *bein hashmashos* of Rabbeinu Tam.
1384    #[must_use]
1385    pub fn bein_hashmashos_rt_2_stars(&self) -> Option<DateTime<Tz>> {
1386        let offset_seconds =
1387            (self.hanetz()? - self.alos_19_8_degrees()?).as_seconds_f64() * (5.0 / 18.0);
1388        let offset_delta = TimeDelta::seconds(offset_seconds.trunc() as i64)
1389            + TimeDelta::nanoseconds((offset_seconds.fract() * 1_000_000_000.0) as i64);
1390        Some(self.shkia()? + offset_delta)
1391    }
1392
1393    // Other Tzais
1394    /// Returns the *tzais hakochavim* (nightfall) based on the
1395    /// opinion of the *Geonim* calculated at the sun's position at 3.7&deg;
1396    /// below the western horizon. This is a very early *zman* and should not be
1397    /// relied on without Rabbinical guidance.
1398    #[must_use]
1399    pub fn tzais_geonim_3_7_degrees(&self) -> Option<DateTime<Tz>> {
1400        self.tzais(&Degrees(3.7))
1401    }
1402
1403    /// Returns the *tzais hakochavim* (nightfall) based on the
1404    /// opinion of the *Geonim* calculated at the sun's position at 3.8&deg;
1405    /// below the western horizon. This is a very early *zman* and should not be
1406    /// relied on without Rabbinical guidance.
1407    #[must_use]
1408    pub fn tzais_geonim_3_8_degrees(&self) -> Option<DateTime<Tz>> {
1409        self.tzais(&Degrees(3.8))
1410    }
1411
1412    /// Returns the *tzais hakochavim* (nightfall) based on the
1413    /// opinion of the *Geonim* calculated as 3/4 of a *mil*, based on a
1414    /// 22.5-minute *mil*, or 16 7/8 minutes. It is the sun's position at
1415    /// 4.37&deg; below the western horizon. This is a very early *zman* and
1416    /// should not be relied on without Rabbinical guidance.
1417    #[must_use]
1418    pub fn tzais_geonim_4_37_degrees(&self) -> Option<DateTime<Tz>> {
1419        self.tzais(&Degrees(4.37))
1420    }
1421
1422    /// Returns the *tzais hakochavim* (nightfall) based on the
1423    /// opinion of the *Geonim* calculated as 3/4 of a *mil* based on a
1424    /// 24-minute *mil*, or 18 minutes. It is the sun's position at 4.61&deg;
1425    /// below the western horizon. This is a very early *zman* and should
1426    /// not be relied on without Rabbinical guidance.
1427    #[must_use]
1428    pub fn tzais_geonim_4_61_degrees(&self) -> Option<DateTime<Tz>> {
1429        self.tzais(&Degrees(4.61))
1430    }
1431
1432    /// Returns the *tzais* (nightfall) based on the opinion of the
1433    /// *Geonim* calculated as 3/4 of a *mil* based on the sun's position at
1434    /// 4.8&deg; below the western horizon. This is based on Rabbi Leo Levi's
1435    /// calculations. This is a very early *zman* and should not be relied on
1436    /// without Rabbinical guidance.
1437    #[must_use]
1438    pub fn tzais_geonim_4_8_degrees(&self) -> Option<DateTime<Tz>> {
1439        self.tzais(&Degrees(4.8))
1440    }
1441
1442    /// Returns the *tzais* (nightfall) based on the opinion of the
1443    /// *Geonim* calculated as 3/4 of a 24-minute *mil*, based on a mil being 24
1444    /// minutes, and is calculated as 18 + 2 + 4 for a total of 24 minutes. It
1445    /// is the sun's position at 5.88&deg; below the western horizon. This is a
1446    /// very early *zman* and should not be relied on without Rabbinical
1447    /// guidance.
1448    #[must_use]
1449    pub fn tzais_geonim_5_88_degrees(&self) -> Option<DateTime<Tz>> {
1450        self.tzais(&Degrees(5.88))
1451    }
1452
1453    /// Returns the *tzais hakochavim* (nightfall) based on the
1454    /// opinion of the *Geonim* calculated at the sun's position at 5.95&deg;
1455    /// below the western horizon. This is a very early *zman* and should not be
1456    /// relied on without Rabbinical guidance.
1457    #[must_use]
1458    pub fn tzais_geonim_5_95_degrees(&self) -> Option<DateTime<Tz>> {
1459        self.tzais(&Degrees(5.95))
1460    }
1461
1462    /// Returns the *tzais* (nightfall) based on the opinion of the
1463    /// *Geonim* as calculated by Rabbi Yechiel Michel Tucazinsky. It is based
1464    /// on of the position of the sun no later than 31 minutes after sunset
1465    /// in Jerusalem the height of the summer solstice and is 28 minutes
1466    /// after *shkiah* around the equinox / equilux. This computes to 6.45&deg;
1467    /// below the western horizon.
1468    #[must_use]
1469    pub fn tzais_geonim_6_45_degrees(&self) -> Option<DateTime<Tz>> {
1470        self.tzais(&Degrees(6.45))
1471    }
1472
1473    /// Returns the *tzais hakochavim* (nightfall) based on the
1474    /// opinion of the *Geonim* calculated when the sun's position 7.083&deg;
1475    /// (or 7&deg; 5′) below the western horizon. This is often referred to
1476    /// as 7&deg;5' or 7&deg; and 5 minutes. This calculation is based on
1477    /// the observation of 3 medium-sized stars by Dr. Baruch (Berthold)
1478    /// Cohn in his luach Tabellen enthaltend die Zeitangaben für den Beginn
1479    /// der Nacht und des Tages für die Breitengrade + 66 bis -38 published
1480    /// in Strasbourg, France in 1899. This calendar was very popular in
1481    /// Europe, and many other calendars based their time on it. Rav Dovid
1482    /// Tzvi Hoffman in his *Sh"Ut Melamed Leho'il* in an exchange of
1483    /// letters with Baruch Cohn in *Orach Chaim* 30 agreed to this *zman*
1484    /// (page 36), as did the *Sh"Ut Bnei Tziyon* and the *Tenuvas
1485    /// Sadeh*. It is very close to the time of the *Mekor Chesed* of the *Sefer
1486    /// chasidim*. It is close to the position of the sun 30 minutes after
1487    /// sunset in Jerusalem around the equinox / equilux, but not Exactly. The
1488    /// actual position of the sun 30 minutes after sunset in Jerusalem at the
1489    /// equilux is 7.205&deg; and 7.199&deg; at the equinox. See *Hazmanim
1490    /// Bahalacha* vol 2, pages 520-521 for more details.
1491    #[must_use]
1492    pub fn tzais_geonim_7_083_degrees(&self) -> Option<DateTime<Tz>> {
1493        self.tzais(&Degrees(7.083))
1494    }
1495
1496    /// Returns *tzais* (nightfall) based on the opinion of the
1497    /// Geonim calculated as 45 minutes after sunset during the summer solstice
1498    /// in New York, when the *neshef* (twilight) is the longest. The sun's
1499    /// position at this time computes to 7.75&deg; below the western horizon.
1500    /// See Igros Moshe Even Haezer 4, Ch. 4 (regarding *tzais* for *krias
1501    /// Shema*). It is also mentioned in Rabbi Heber's *Shaarei Zmanim* on in
1502    /// chapter 10 (page 87) and chapter 12 (page 108). Also see the time of 45
1503    /// minutes in Rabbi Simcha Bunim Cohen's The radiance of Shabbos as the
1504    /// earliest *zman* for New York. This *zman* is also listed in the *Divrei
1505    /// Shalom* Vol. III, chapter 75, and *Bais Av"i* Vol. III, chapter 117.
1506    /// This *zman* is also listed in the *Divrei Shalom* etc. chapter 177
1507    /// (FIXME - could not be located). Since this *zman* depends on the level
1508    /// of light, Rabbi Yaakov Shakow presented this degree-based calculation to
1509    /// Rabbi Rabbi Shmuel Kamenetsky who agreed to it.
1510    #[must_use]
1511    pub fn tzais_geonim_7_67_degrees(&self) -> Option<DateTime<Tz>> {
1512        self.tzais(&Degrees(7.67))
1513    }
1514
1515    /// Returns *tzais* (nightfall) when the sun is 8.5&deg; below the geometric
1516    /// horizon (90&deg;) after sunset, a time that Rabbi Meir Posen in his the
1517    /// *Ohr Meir* calculated that 3 small stars are visible, which is later
1518    /// than the required 3 medium stars. This calculation is based on the sun's
1519    /// position below the horizon 36 minutes after sunset in Jerusalem around
1520    /// the equinox / equilux.
1521    #[must_use]
1522    pub fn tzais_geonim_8_5_degrees(&self) -> Option<DateTime<Tz>> {
1523        self.tzais(&Degrees(8.5))
1524    }
1525
1526    /// Returns the *tzais* (nightfall) based on the calculations
1527    /// used in the *Luach Itim Lebinah* as the stringent time for *tzais*. It
1528    /// is calculated at the sun's position at 9.3&deg; below the western
1529    /// horizon.
1530    #[must_use]
1531    pub fn tzais_geonim_9_3_degrees(&self) -> Option<DateTime<Tz>> {
1532        self.tzais(&Degrees(9.3))
1533    }
1534
1535    /// Returns the *tzais* (nightfall) based on the opinion of the
1536    /// *Geonim* calculated as 60 minutes after sunset around the equinox /
1537    /// equilux, the day that a solar hour is 60 minutes in New York. The sun's
1538    /// position at this time computes to 9.75&deg; below the western horizon.
1539    /// This is the opinion of Rabbi Eliyahu Henkin. This also follows the
1540    /// opinion of Rabbi Shmuel Kamenetsky. Rabbi Yaakov Shakow presented
1541    /// these degree-based times to Rabbi Shmuel Kamenetsky who agreed to
1542    /// them.
1543    #[must_use]
1544    pub fn tzais_geonim_9_75_degrees(&self) -> Option<DateTime<Tz>> {
1545        self.tzais(&Degrees(9.75))
1546    }
1547}
1548
1549/// When to use elevation for *zmanim* calculations. See the documentation of
1550/// [`zmanim_calculator`] for some discussion of this
1551#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1552pub enum UseElevation {
1553    /// Never use elevation
1554    No,
1555    /// Only use elevation directly for *hanetz* and *shkia*
1556    HanetzShkia,
1557    /// Always use elevation
1558    All,
1559}
1560
1561impl UseElevation {
1562    /// Convert the `UseElevation` into a `bool` for
1563    /// [`zmanim_calculator`] functions. The param
1564    /// `hanetz_or_shkia` should be `true` if the calling function is
1565    /// calculating *hanetz* or *shkia*, and `false` otherwise
1566    #[must_use]
1567    pub const fn to_bool(&self, hanetz_or_shkia: bool) -> bool {
1568        match &self {
1569            Self::No => false,
1570            Self::HanetzShkia => hanetz_or_shkia,
1571            Self::All => true,
1572        }
1573    }
1574}