diff --git a/src/main/java/com/kosherjava/zmanim/ComprehensiveZmanimCalendar.java b/src/main/java/com/kosherjava/zmanim/ComprehensiveZmanimCalendar.java
index 05866ccb..56a250e5 100644
--- a/src/main/java/com/kosherjava/zmanim/ComprehensiveZmanimCalendar.java
+++ b/src/main/java/com/kosherjava/zmanim/ComprehensiveZmanimCalendar.java
@@ -152,7 +152,7 @@ public class ComprehensiveZmanimCalendar extends ZmanimCalendar {
* @see #getMisheyakir11Point5Degrees()
*/
protected static final double ZENITH_11_POINT_5 = GEOMETRIC_ZENITH + 11.5;
-
+
/**
* The zenith of 12.85° below {@link GEOMETRIC_ZENITH geometric zenith} (90°).
* @see #getMisheyakir12Point85Degrees()
@@ -514,7 +514,11 @@ public long getShaahZmanis96MinutesZmanis() {
* @see #setAteretTorahSunsetOffset(double)
*/
public long getShaahZmanisAteretTorah() {
- return getTemporalHour(getAlos72Zmanis(), getTzaisAteretTorah());
+ ShaahZmanis shaahZmanisTypePrevious = shaahZmanisType;
+ setShaahZmanisType(ShaahZmanis.GRA);
+ long result = getTemporalHour(getAlos72Zmanis(), getTzaisAteretTorah());
+ setShaahZmanisType(shaahZmanisTypePrevious);
+ return result;
}
/**
@@ -940,7 +944,7 @@ public Instant getAlos19Degrees() {
public Instant getAlos19Point8Degrees() {
return getSunriseOffsetByDegrees(ZENITH_19_POINT_8);
}
-
+
/**
* This method returns misheyakir based on the position of the sun {@link ZENITH_12_POINT_85 12.85°}
* below {@link GEOMETRIC_ZENITH geometric zenith} (90°). This is based on the position of the sun slightly
@@ -973,7 +977,7 @@ public Instant getAlos19Point8Degrees() {
* hadchak. Lechatchila, a later zman should be used. There is no current plan to remove
* this method from the API, and this deprecation is intended to notify developers to add an alert to users of
* the risk of using it.
- *
+ *
* @return The Instant of misheyakir. If the calculation can't be computed such as northern and
* southern locations even south of the Arctic Circle and north of the Antarctic Circle where the sun may
* not reach low enough below the horizon for this calculation, a null will be returned. See
@@ -1696,7 +1700,7 @@ public Instant getMinchaGedolaAhavatShalom() {
* returned. Since this calculation can be an offset of chatzos (if 30 clock minutes > 1/2 of a shaah
* zmanis), even if {@link #isUseAstronomicalChatzosForOtherZmanim()} is false, this mincha
* time may be affected by {@link #isUseAstronomicalChatzos()}.
- *
+ *
* @param minchaGedola
* the mincha gedola to be compared to {@link #getMinchaGedola30Minutes()}.
* @return the Instant of the later of {@link #getMinchaGedolaGRA()} and {@link #getMinchaGedola30Minutes()}.
@@ -1706,7 +1710,7 @@ public Instant getMinchaGedolaAhavatShalom() {
* @see #getMinchaGedolaGRA()
* @see #getMinchaGedola30Minutes()
* @see #isUseAstronomicalChatzos()
- *
+ *
*/
public Instant getMinchaGedolaGreaterThan30(Instant minchaGedola) {
if (getMinchaGedola30Minutes() == null || minchaGedola == null) {
@@ -1716,7 +1720,7 @@ public Instant getMinchaGedolaGreaterThan30(Instant minchaGedola) {
: minchaGedola;
}
}
-
+
/**
* This is a convenience method that returns the later of {@link #getMinchaGedolaGRA()} and
* {@link #getMinchaGedola30Minutes()}. In the winter when 1/2 of a {@link #getShaahZmanisGRA() shaah zmanis} is
@@ -2072,7 +2076,7 @@ public Instant getPlagHamincha18Degrees() {
* shkiah), and if used lekula can result in chillul Shabbos etc. There is no
* current plan to remove this method from the API, and this deprecation is intended to alert developers
* of the danger of using it.
- *
+ *
* @return the Instant of the plag. If the calculation can't be computed such as northern and southern
* locations even south of the Arctic Circle and north of the Antarctic Circle where the sun may not reach
* low enough below the horizon for this calculation, a null will be returned. See detailed
@@ -2149,7 +2153,7 @@ public Instant getPlagAhavatShalom() {
* Arctic Circle and north of the Antarctic Circle where the sun may not reach low enough below the horizon
* for this calculation, a null will be returned. See detailed explanation on top of the
* {@link AstronomicalCalendar} documentation.
- *
+ *
* @see #getBainHashmashosRT58Point5Minutes()
*/
public Instant getBainHashmashosRT13Point24Degrees() {
@@ -2259,7 +2263,7 @@ public Instant getBainHashmashosYereim18Minutes() {
public Instant getBainHashmashosYereim3Point05Degrees() {
return getSunsetOffsetByDegrees(ZENITH_MINUS_3_POINT_05);
}
-
+
/**
* This method returns the beginning of bain hashmashos (twilight) according to the Yereim (Rabbi Eliezer of Metz) calculated as 16.875
@@ -2303,7 +2307,7 @@ public Instant getBainHashmashosYereim16Point875Minutes() {
public Instant getBainHashmashosYereim2Point8Degrees() {
return getSunsetOffsetByDegrees(ZENITH_MINUS_2_POINT_8);
}
-
+
/**
* This method returns the beginning of bain hashmashos (twilight) according to the Yereim (Rabbi Eliezer of Metz) calculated as 13.5 minutes
@@ -2420,7 +2424,7 @@ public Instant getTzaisGeonim5Point95Degrees() {
* This does not cover the 35.28 seconds it takes to walk 49 amos (the heref ayin of bain hashmashos
* of Rav Yosi) at the pace of a 24-minute mil. See {@link #getTzaisGeonim4Point8Degrees()} for a time that covers the
* heref ayin.
- *
+ *
* @return the Instant representing the time when the sun is 4.66° below sea level. If the calculation
* can't be computed such as northern and southern locations even south of the Arctic Circle and north of
* the Antarctic Circle where the sun may not reach low enough below the horizon for this calculation, a
@@ -2484,7 +2488,7 @@ public Instant getTzaisGeonim4Point42Degrees() {
public Instant getTzaisGeonim4Point8Degrees() {
return getSunsetOffsetByDegrees(ZENITH_4_POINT_8);
}
-
+
/**
* This method returns the tzais (nightfall) based on the opinion of the Geonim as calculated by Rabbi Yechiel Michel Tucazinsky as the position of
@@ -2497,7 +2501,7 @@ public Instant getTzaisGeonim4Point8Degrees() {
* should be noted that this differs from the 6.1° / 6.2° calculation for Rabbi Tucazinsky's time as calculated by the
* Hazmanim Bahalacha Vol II chapter 50:7 (page 515). Calculations show that 6.45° at the equinox is 26.5 minutes after
* shkiah around the equinox /
- * equilux.
+ * equilux.
*
* @return the Instant representing the time when the sun is 6.45° below sea level. If the
* calculation can't be computed such as northern and southern locations even south of the Arctic Circle and
@@ -3056,7 +3060,7 @@ public Instant getFixedLocalChatzosHayom() {
*/
public Instant getSofZmanKidushLevanaBetweenMoldos(Instant alos, Instant tzais) {
JewishCalendar jewishCalendar = new JewishCalendar(getLocalDate());
-
+
// Do not calculate for impossible dates, but account for extreme cases. In the extreme case of Rapa Iti in French
// Polynesia on Dec 2027 when kiddush Levana 3 days can be said on Rosh Chodesh, the sof zman Kiddush Levana
// will be on the 12th of the Teves. In the case of Anadyr, Russia on Jan, 2071, sof zman Kiddush Levana between the
@@ -3156,7 +3160,7 @@ public Instant getSofZmanKidushLevanaBetweenMoldos() {
*/
public Instant getSofZmanKidushLevana15Days(Instant alos, Instant tzais) {
JewishCalendar jewishCalendar = new JewishCalendar(getLocalDate());
-
+
// Do not calculate for impossible dates, but account for extreme cases. In the extreme case of Rapa Iti in
// French Polynesia on Dec 2027 when kiddush Levana 3 days can be said on Rosh Chodesh, the sof zman Kiddush
// Levana will be on the 12th of the Teves. in the case of Anadyr, Russia on Jan, 2071, sof zman kiddush levana will
@@ -3515,7 +3519,7 @@ public Instant getSofZmanBiurChametzMGA16Point1Degrees() {
* According to the Baal Hatanya, shkiah amiti, true (halachic) sunset, is when the top of the
* sun's disk disappears from view at an elevation similar to the mountains of Eretz Yisrael.
* This time is calculated as the point at which the center of the sun's disk is 1.583 degrees below the horizon.
- * A method that returns a shaah zmanis ({@link #getTemporalHour(Instant, Instant) temporal hour}) calculated
+ * A method that returns a shaah zmanis ({@link #getTemporalHour(Instant, Instant) temporal hour}) calculated
* based on the Baal Hatanya's netz
* amiti and shkiah amiti using a dip of 1.583° below the sea level horizon. This calculation divides
* the day based on the opinion of the Baal Hatanya that the day runs from {@link #getSunriseBaalHatanya() netz amiti}
@@ -3717,7 +3721,7 @@ public Instant getPlagHaminchaBaalHatanya() {
public Instant getTzaisBaalHatanya() {
return getSunsetOffsetByDegrees(ZENITH_6_DEGREES);
}
-
+
/**
* This method returns Rav Moshe Feinstein's opinion of the
* calculation of sof zman krias shema (latest time to recite Shema in the morning) according to the
@@ -3939,7 +3943,7 @@ public Instant getSamuchLeMinchaKetanaGRA() {
}
/**
- *
+ *
* A method for calculating samuch lemincha ketana, / near mincha ketana time that is half an hour before
* {@link #getMinchaKetanaGRA()} or is 9 * shaos zmaniyos (solar hours) after the start of the day, calculated based
* on a day from and ending a day starting at {@link #getMinchaGedola16Point1Degrees() alos 16.1°} and ending
@@ -3979,7 +3983,7 @@ public Instant getSamuchLeMinchaKetana16Point1Degrees() {
public Instant getSamuchLeMinchaKetana72Minutes() {
return getSamuchLeMinchaKetana(getAlos72Minutes(), getTzais72Minutes(), true);
}
-
+
/**
* {@summary A method that returns {@link #getSunsetBasedOnElevationSetting() sunset} if it occurs, or the time that the sun
* is at its westernmost position (azimuth of 270°), if sunset will not occur that day. In Polar regions (the Arctic or Antarctic
@@ -3993,7 +3997,7 @@ public Instant getSamuchLeMinchaKetana72Minutes() {
* "https://hebrewbooks.org/pdfpager.aspx?req=1401&pgnum=461">רב פעלים – חלק ב׳, סוד ישרים ס׳ ד׳. This time is close to six hours
* after {@link #getSunTransit() astronomical chatzos hayom}, but depending on the time of year and location in the
* Arctic / Antarctic, it can be up to 46 minutes before or after this time.
- *
+ *
* @return sunset if it occurs, or the time that the sun will reach its westernmost position (azimuth 270°), if sunset will
* not occur that day. If there is no sunset this day, and the azimuth 270° will not occur, a null will
* be returned.
@@ -4008,7 +4012,7 @@ public Instant getSunsetOrWesternmostSolarAzimuth() {
}
return getTimeAtAzimuth(270);
}
-
+
/**
* {@summary A method that returns {@link #getSunriseBasedOnElevationSetting() sunrise} if it occurs, or the time that the sun
* is at its easternmost position (azimuth of 90°), if sunrise will not occur that day. In Polar regions (the Arctic or Antarctic
@@ -4022,7 +4026,7 @@ public Instant getSunsetOrWesternmostSolarAzimuth() {
* "https://hebrewbooks.org/pdfpager.aspx?req=1401&pgnum=461">רב פעלים – חלק ב׳, סוד ישרים ס׳ ד׳. This time is close to six hours
* before {@link #getSunTransit() astronomical chatzos hayom}, but depending on the time of year and location in the
* Arctic / Antarctic, it can be up to 46 minutes before or after this time.
- *
+ *
* @return sunrise if it occurs, or the time that the sun will reach its easternmost position (azimuth 90°), if sunrise will
* not occur that day. If there is no sunrise this day, and the azimuth 90° will not occur, a null will
* be returned.
@@ -4037,7 +4041,7 @@ public Instant getSunriseOrEasternmostSolarAzimuth() {
}
return getTimeAtAzimuth(90);
}
-
+
/**
* @see java.lang.Object#equals(Object)
*/
@@ -4061,4 +4065,34 @@ public boolean equals(Object object) {
public int hashCode() {
return 37 * super.hashCode() + Double.hashCode(ateretTorahSunsetOffset);
}
+
+ @Override
+ public long getShaahZmanis() {
+ switch (shaahZmanisType) {
+ case ATERET:
+ return getShaahZmanisAteretTorah();
+ case BAAL_HATANYA:
+ return getShaahZmanisBaalHatanya();
+ case DEGREES_16POINT1:
+ return getShaahZmanis16Point1Degrees();
+ case DEGREES_18:
+ return getShaahZmanis18Degrees();
+ case DEGREES_19POINT8:
+ return getShaahZmanis19Point8Degrees();
+ case DEGREES_26:
+ return getShaahZmanis26Degrees();
+ case MINUTES_60:
+ return getShaahZmanis60Minutes();
+ case MINUTES_72:
+ return getShaahZmanis72Minutes();
+ case MINUTES_90:
+ return getShaahZmanis90Minutes();
+ case MINUTES_96:
+ return getShaahZmanis96Minutes();
+ case MINUTES_120:
+ return getShaahZmanis120Minutes();
+ default:
+ return super.getShaahZmanis();
+ }
+ }
}
diff --git a/src/main/java/com/kosherjava/zmanim/ShaahZmanis.java b/src/main/java/com/kosherjava/zmanim/ShaahZmanis.java
new file mode 100644
index 00000000..2f16c65b
--- /dev/null
+++ b/src/main/java/com/kosherjava/zmanim/ShaahZmanis.java
@@ -0,0 +1,36 @@
+package com.kosherjava.zmanim;
+
+/**
+ * Enumeration of shaah zmanis (temporal hour).
+ *
+ * @author © Moshe Waisberg 2017 - 2024
+ */
+public enum ShaahZmanis {
+
+ /** According to the opinion of the GRA and the Baal Hatanya. */
+ GRA,
+ /** According to the opinion of the Magen Avraham. */
+ MGA,
+ /** According to the opinion of the Yeshivat Ateret Torah. */
+ ATERET,
+ /** According to the opinion of the Baal Hatanya. */
+ BAAL_HATANYA,
+ /** Calculated using a dip of 60 minutes. */
+ MINUTES_60,
+ /** Calculated using a dip of 72 minutes. */
+ MINUTES_72,
+ /** Calculated using a dip of 90 minutes. */
+ MINUTES_90,
+ /** Calculated using a dip of 96 minutes. */
+ MINUTES_96,
+ /** Calculated using a dip of 120 minutes. */
+ MINUTES_120,
+ /** Calculated using a dip of 16.1°. */
+ DEGREES_16POINT1,
+ /** Calculated using a dip of 18°. */
+ DEGREES_18,
+ /** Calculated using a dip of 19.8°. */
+ DEGREES_19POINT8,
+ /** Calculated using a dip of 26°. */
+ DEGREES_26
+}
diff --git a/src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java b/src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java
index 3a0c4b58..975b9a0f 100644
--- a/src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java
+++ b/src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java
@@ -68,7 +68,9 @@
* @author © Eliyahu Hershfeld 2004 - 2026
*/
public class ZmanimCalendar extends AstronomicalCalendar {
-
+
+ protected ShaahZmanis shaahZmanisType = ShaahZmanis.GRA;
+
/**
* Is elevation factored in for some zmanim (see {@link isUseElevation()} for additional information).
* @see isUseElevation()
@@ -261,7 +263,7 @@ public void setUseAstronomicalChatzosForOtherZmanim(boolean useAstronomicalChatz
*/
protected Instant getSunriseBasedOnElevationSetting() {
if (isUseElevation()) {
- return super.getSunrise();
+ return getSunrise();
}
return getSeaLevelSunrise();
}
@@ -277,7 +279,7 @@ protected Instant getSunriseBasedOnElevationSetting() {
*/
protected Instant getSunsetBasedOnElevationSetting() {
if (isUseElevation()) {
- return super.getSunset();
+ return getSunset();
}
return getSeaLevelSunset();
}
@@ -1204,7 +1206,7 @@ public long getShaahZmanisGRA() {
* based zmanim.
*/
public Instant getZmanisBasedOffset(double hours) {
- long shaahZmanis = getShaahZmanisGRA();
+ long shaahZmanis = getShaahZmanis();
if (shaahZmanis == Long.MIN_VALUE || hours == 0) {
return null;
}
@@ -1546,4 +1548,28 @@ public int hashCode() {
return Objects.hash(super.hashCode(), useElevation, useAstronomicalChatzos,
useAstronomicalChatzosForOtherZmanim, Double.hashCode(candleLightingOffset));
}
+
+ /**
+ * A method that returns a shaah zmanis ( {@link #getTemporalHour(Instant, Instant)} temporal hour}).
+ *
+ * @return the long millisecond length of a shaah zmanis.
+ * @see #getShaahZmanisGRA()
+ */
+ public long getShaahZmanis() {
+ switch (shaahZmanisType) {
+ case MGA:
+ return getShaahZmanis72Minutes();
+ case GRA:
+ default:
+ return getShaahZmanisGRA();
+ }
+ }
+
+ /**
+ * Set the type of shaah zmanis.
+ * @param type the type.
+ */
+ public void setShaahZmanisType(ShaahZmanis type) {
+ shaahZmanisType = type;
+ }
}
diff --git a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/ShaahZmanisTest.java b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/ShaahZmanisTest.java
new file mode 100644
index 00000000..ed93875e
--- /dev/null
+++ b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/ShaahZmanisTest.java
@@ -0,0 +1,127 @@
+package com.kosherjava.zmanim.hebrewcalendar;
+
+import static org.junit.Assert.assertTrue;
+
+import com.kosherjava.zmanim.ComprehensiveZmanimCalendar;
+import com.kosherjava.zmanim.ShaahZmanis;
+import com.kosherjava.zmanim.ZmanimCalendar;
+import com.kosherjava.zmanim.util.GeoLocation;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.time.LocalDate;
+import java.time.Month;
+import java.time.ZoneId;
+import java.util.TimeZone;
+
+public class ShaahZmanisTest {
+
+ @Test
+ public void testTemporalHour() {
+ ZmanimCalendar calendar = new ComprehensiveZmanimCalendar();
+ long hour;
+
+ hour = calendar.getTemporalHour();
+ assertTrue(hour > 0);
+ hour = calendar.getShaahZmanis();
+ assertTrue(hour > 0);
+ }
+
+ @Test
+ public void testShaahZmanis() {
+ GeoLocation location = new GeoLocation("test", 0.0, 0.0, ZoneId.of("UTC"));
+ ComprehensiveZmanimCalendar calendar = new ComprehensiveZmanimCalendar(location);
+ calendar.setLocalDate(LocalDate.of(2022, Month.JUNE, 22));
+ long hour;
+ long delta = 1000;
+
+ hour = calendar.getShaahZmanis120Minutes();
+ assertEquals(4836877, hour, delta);
+ hour = calendar.getShaahZmanis120MinutesZmanis();
+ assertEquals(4849169, hour, delta);
+ hour = calendar.getShaahZmanis16Point1Degrees();
+ assertEquals(4304341, hour, delta);
+ hour = calendar.getShaahZmanis18Degrees();
+ assertEquals(4387928, hour, delta);
+ hour = calendar.getShaahZmanis19Point8Degrees();
+ assertEquals(4467292, hour, delta);
+ hour = calendar.getShaahZmanis26Degrees();
+ assertEquals(4742324, hour, delta);
+ hour = calendar.getShaahZmanis60Minutes();
+ assertEquals(4236877, hour, delta);
+ hour = calendar.getShaahZmanis72Minutes();
+ assertEquals(4356877, hour, delta);
+ hour = calendar.getShaahZmanis72MinutesZmanis();
+ assertEquals(4364252, hour, delta);
+ hour = calendar.getShaahZmanis90Minutes();
+ assertEquals(4536877, hour, delta);
+ hour = calendar.getShaahZmanis90MinutesZmanis();
+ assertEquals(4546096, hour, delta);
+ hour = calendar.getShaahZmanis96Minutes();
+ assertEquals(4596877, hour, delta);
+ hour = calendar.getShaahZmanis96MinutesZmanis();
+ assertEquals(4606710, hour, delta);
+ hour = calendar.getShaahZmanisAteretTorah();
+ assertEquals(4200564, hour, delta);
+ hour = calendar.getShaahZmanisBaalHatanya();
+ assertEquals(3669565, hour, delta);
+ hour = calendar.getShaahZmanisGRA();
+ assertEquals(3636877, hour, delta);
+ hour = calendar.getShaahZmanis72Minutes();
+ assertEquals(4356877, hour, delta);
+ }
+
+ @Test
+ public void testShaahZmanisType() {
+ GeoLocation location = new GeoLocation("test", 0.0, 0.0, ZoneId.of("UTC"));
+ ComprehensiveZmanimCalendar calendar = new ComprehensiveZmanimCalendar(location);
+ calendar.setLocalDate(LocalDate.of(2022, Month.JUNE, 22));
+ long hour;
+ long delta = 1000;
+
+ calendar.setShaahZmanisType(ShaahZmanis.MINUTES_120);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4836877, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.DEGREES_16POINT1);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4304341, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.DEGREES_18);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4387928, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.DEGREES_19POINT8);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4467292, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.DEGREES_26);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4742324, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.MINUTES_60);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4236877, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.MINUTES_72);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4356877, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.MINUTES_90);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4536877, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.MINUTES_96);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4596877, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.ATERET);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4200564, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.BAAL_HATANYA);
+ hour = calendar.getShaahZmanis();
+ assertEquals(3669565, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.GRA);
+ hour = calendar.getShaahZmanis();
+ assertEquals(3636877, hour, delta);
+ calendar.setShaahZmanisType(ShaahZmanis.MGA);
+ hour = calendar.getShaahZmanis();
+ assertEquals(4356877, hour, delta);
+ }
+
+ private static void assertEquals(long expected, long actual, long delta) {
+ Assert.assertEquals((float) expected, (float) actual, (float) delta);
+ }
+}