001/* 002 * Zmanim Java API 003 * Copyright (C) 2004-2023 Eliyahu Hershfeld 004 * 005 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General 006 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) 007 * any later version. 008 * 009 * This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied 010 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 011 * details. 012 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to 013 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA, 014 * or connect to: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html 015 */ 016package com.kosherjava.zmanim; 017 018import java.util.Calendar; 019import java.util.Date; 020 021import com.kosherjava.zmanim.hebrewcalendar.JewishCalendar; 022import com.kosherjava.zmanim.util.AstronomicalCalculator; 023import com.kosherjava.zmanim.util.GeoLocation; 024 025/** 026 * The ZmanimCalendar is a specialized calendar that can calculate sunrise, sunset and Jewish <em>zmanim</em> 027 * (religious times) for prayers and other Jewish religious duties. This class contains the main functionality of the 028 * <em>Zmanim</em> library. For a much more extensive list of <em>zmanim</em>, use the {@link ComplexZmanimCalendar} that 029 * extends this class. See documentation for the {@link ComplexZmanimCalendar} and {@link AstronomicalCalendar} for 030 * simple examples on using the API. 031 * <strong>Elevation based <em>zmanim</em> (even sunrise and sunset) should not be used <em>lekula</em> without the guidance 032 * of a <em>posek</em></strong>. According to Rabbi Dovid Yehudah Bursztyn in his 033 * <a href="https://www.worldcat.org/oclc/1158574217">Zmanim Kehilchasam, 7th edition</a> chapter 2, section 7 (pages 181-182) 034 * and section 9 (pages 186-187), no <em>zmanim</em> besides sunrise and sunset should use elevation. However, Rabbi Yechiel 035 * Avrahom Zilber in the <a href="https://hebrewbooks.org/51654">Birur Halacha Vol. 6</a> Ch. 58 Pages 036 * <a href="https://hebrewbooks.org/pdfpager.aspx?req=51654&pgnum=42">34</a> and 037 * <a href="https://hebrewbooks.org/pdfpager.aspx?req=51654&pgnum=50">42</a> is of the opinion that elevation should be 038 * accounted for in <em>zmanim</em> calculations. Related to this, Rabbi Yaakov Karp in <a href= 039 * "https://www.worldcat.org/oclc/919472094">Shimush Zekeinim</a>, Ch. 1, page 17 states that obstructing horizons should 040 * be factored into <em>zmanim</em> calculations. The setting defaults to false (elevation will not be used for 041 * <em>zmanim</em> calculations besides sunrise and sunset), unless the setting is changed to true in {@link 042 * #setUseElevation(boolean)}. This will impact sunrise and sunset-based <em>zmanim</em> such as {@link #getSunrise()}, 043 * {@link #getSunset()}, {@link #getSofZmanShmaGRA()}, <em>alos</em>-based <em>zmanim</em> such as {@link #getSofZmanShmaMGA()} 044 * that are based on a fixed offset of sunrise or sunset and <em>zmanim</em> based on a percentage of the day such as 045 * {@link ComplexZmanimCalendar#getSofZmanShmaMGA90MinutesZmanis()} that are based on sunrise and sunset. Even when set to 046 * true it will not impact <em>zmanim</em> that are a degree-based offset of sunrise and sunset, such as {@link 047 * ComplexZmanimCalendar#getSofZmanShmaMGA16Point1Degrees()} or {@link ComplexZmanimCalendar#getSofZmanShmaBaalHatanya()} since 048 * these <em>zmanim</em> are not linked to sunrise or sunset times (the calculations are based on the astronomical definition of 049 * sunrise and sunset calculated in a vacuum with the solar radius above the horizon), and are therefore not impacted by the use 050 * of elevation. 051 * For additional information on the <em>halachic</em> impact of elevation on <em>zmanim</em> see: 052 * <ul> 053 * <li><a href="https://www.nli.org.il/en/books/NNL_ALEPH002542826/NLI">Zmanei Halacha Lema'aseh</a> 4th edition by <a href= 054 * "http://beinenu.com/rabbis/%D7%94%D7%A8%D7%91-%D7%99%D7%93%D7%99%D7%93%D7%99%D7%94-%D7%9E%D7%A0%D7%AA">Rabbi Yedidya Manat</a>. 055 * See section 1, pages 11-12 for a very concise write-up, with details in section 2, pages 37 - 63 and 133 - 151.</li> 056 * <li><a href="https://www.worldcat.org/oclc/1158574217">Zmanim Kehilchasam</a> 7th edition, by Rabbi Dovid Yehuda Burstein, vol 1, 057 * chapter 2, pages 95 - 188.</li> 058 * <li><a href="https://www.worldcat.org/oclc/36089452">Hazmanim Bahalacha</a> by Rabbi Chaim Banish , perek 7, pages 53 - 63.</li> 059 * </ul> 060 * 061 * <p><b>Note:</b> It is important to read the technical notes on top of the {@link AstronomicalCalculator} documentation 062 * before using this code. 063 * <p>I would like to thank <a href="https://www.worldcat.org/search?q=au%3AShakow%2C+Yaakov">Rabbi Yaakov Shakow</a>, the 064 * author of Luach Ikvei Hayom who spent a considerable amount of time reviewing, correcting and making suggestions on the 065 * documentation in this library. 066 * <h2>Disclaimer:</h2> I did my best to get accurate results, but please double-check before relying on these 067 * <em>zmanim</em> for <em>halacha lema'aseh</em>. 068 * 069 * @author © Eliyahu Hershfeld 2004 - 2023 070 */ 071public class ZmanimCalendar extends AstronomicalCalendar { 072 073 /** 074 * Is elevation factored in for some <em>zmanim</em> (see {@link #isUseElevation()} for additional information). 075 * @see #isUseElevation() 076 * @see #setUseElevation(boolean) 077 */ 078 private boolean useElevation; 079 080 /** 081 * Is elevation above sea level calculated for times besides sunrise and sunset. According to Rabbi Dovid Yehuda 082 * Bursztyn in his <a href="https://www.worldcat.org/oclc/659793988">Zmanim Kehilchasam (second edition published 083 * in 2007)</a> chapter 2 (pages 186-187) no <em>zmanim</em> besides sunrise and sunset should use elevation. However 084 * Rabbi Yechiel Avrahom Zilber in the <a href="https://hebrewbooks.org/51654">Birur Halacha Vol. 6</a> Ch. 58 Pages 085 * <a href="https://hebrewbooks.org/pdfpager.aspx?req=51654&pgnum=42">34</a> and <a href= 086 * "https://hebrewbooks.org/pdfpager.aspx?req=51654&pgnum=50">42</a> is of the opinion that elevation should be 087 * accounted for in <em>zmanim</em> calculations. Related to this, Rabbi Yaakov Karp in <a href= 088 * "https://www.worldcat.org/oclc/919472094">Shimush Zekeinim</a>, Ch. 1, page 17 states that obstructing horizons 089 * should be factored into <em>zmanim</em> calculations.The setting defaults to false (elevation will not be used for 090 * <em>zmanim</em> calculations), unless the setting is changed to true in {@link #setUseElevation(boolean)}. This will 091 * impact sunrise and sunset based <em>zmanim</em> such as {@link #getSunrise()}, {@link #getSunset()}, 092 * {@link #getSofZmanShmaGRA()}, alos based <em>zmanim</em> such as {@link #getSofZmanShmaMGA()} that are based on a 093 * fixed offset of sunrise or sunset and <em>zmanim</em> based on a percentage of the day such as {@link 094 * ComplexZmanimCalendar#getSofZmanShmaMGA90MinutesZmanis()} that are based on sunrise and sunset. It will not impact 095 * <em>zmanim</em> that are a degree based offset of sunrise and sunset, such as 096 * {@link ComplexZmanimCalendar#getSofZmanShmaMGA16Point1Degrees()} or {@link ComplexZmanimCalendar#getSofZmanShmaBaalHatanya()}. 097 * 098 * @return if the use of elevation is active 099 * 100 * @see #setUseElevation(boolean) 101 */ 102 public boolean isUseElevation() { 103 return useElevation; 104 } 105 106 /** 107 * Sets whether elevation above sea level is factored into <em>zmanim</em> calculations for times besides sunrise and sunset. 108 * See {@link #isUseElevation()} for more details. 109 * @see #isUseElevation() 110 * 111 * @param useElevation set to true to use elevation in <em>zmanim</em> calculations 112 */ 113 public void setUseElevation(boolean useElevation) { 114 this.useElevation = useElevation; 115 } 116 117 /** 118 * Is astronomical <em>chatzos</em> used for <em>zmanim</em> calculations. The default value of <code>true</code> will 119 * keep the standard astronomical <em>chatzos</em> calculation, while setting it to <code>false</code> will use half of 120 * a solar day calculation for <em>chatzos</em>. 121 * @see #isUseAstronomicalChatzos() 122 * @see #setUseAstronomicalChatzos(boolean) 123 * @see #getChatzos() 124 * @see #getSunTransit() 125 * @see #getChatzosAsHalfDay() 126 * @see #useAstronomicalChatzosForOtherZmanim 127 */ 128 private boolean useAstronomicalChatzos = true; 129 130 /** 131 * Is {@link #getSunTransit() astronomical <em>chatzos</em>} used for {@link #getChatzos()} for enhanced accuracy. For 132 * example as the day is lengthens, the second half of the day is longer than the first and astronomical <em>chatzos</em> 133 * would be a drop earlier than half of the time between sunrise and sunset. 134 * 135 * @todo In the future, if this is set to true, the following may change to enhance accuracy. {@link #getSofZmanShmaGRA() 136 * <em>Sof zman Shma</em> GRA} would be calculated as 3 <em>shaaos zmaniyos</em> after sunrise, but the <em>shaaos 137 * zmaniyos</em> would be calculated a a 6th of the time between sunrise and <em>chatzos</em>, as opposed to a 12th of the 138 * time between sunrise and sunset. {@link #getMinchaGedola() <em>mincha gedola</em>} will be calculated as half a 139 * <em>shaah zmanis</em> of afternoon hours (a 6th of the time between <em>chatzos</em> and sunset after astronomical 140 * <em>chatzos</em> as opposed to 6.5 <em>shaaos zmaniyos</em> after sunrise. {@link #getPlagHamincha() <em>Plag 141 * hamincha</em>} would be calculated as 4.75 <em>shaaos zmaniyos</em> after astronomical <em>chatzos</em> as opposed to 10.75 142 * <em>shaaos zmaniyos</em> after sunrise. Etc. 143 * 144 * @return if the use of astronomical <em>chatzos</em> is active. 145 * @see #useAstronomicalChatzos 146 * @see #setUseAstronomicalChatzos(boolean) 147 * @see #getChatzos() 148 * @see #getSunTransit() 149 * @see #getChatzosAsHalfDay() 150 * @see #isUseAstronomicalChatzosForOtherZmanim() 151 */ 152 public boolean isUseAstronomicalChatzos() { 153 return useAstronomicalChatzos; 154 } 155 156 /** 157 * Sets if astronomical <em>chatzos</em> should be used in calculations of other <em>zmanim</em> for enhanced accuracy. 158 * @param useAstronomicalChatzos set to true to use astronomical in <em>chatzos</em> in <em>zmanim</em> calculations. 159 * @see #useAstronomicalChatzos 160 * @see #isUseAstronomicalChatzos() 161 * @see #getChatzos() 162 * @see #getSunTransit() 163 * @see #getChatzosAsHalfDay() 164 * @see #setUseAstronomicalChatzosForOtherZmanim(boolean) 165 */ 166 public void setUseAstronomicalChatzos(boolean useAstronomicalChatzos) { 167 this.useAstronomicalChatzos = useAstronomicalChatzos; 168 } 169 170 /** 171 * Is astronomical <em>chatzos</em> used for <em>zmanim</em> calculations besides <em>chatzos</em> itself for enhanced 172 * accuracy. The default value of <code>false</code> will keep the standard start to end of day calculations, while setting 173 * it to <code>true</code> will use half of a solar day calculation for <em>zmanim</em>. 174 * @see #isUseAstronomicalChatzosForOtherZmanim() 175 * @see #setUseAstronomicalChatzosForOtherZmanim(boolean) 176 * @see #isUseAstronomicalChatzos() 177 * @see #setUseAstronomicalChatzos(boolean) 178 * @see #getChatzos() 179 */ 180 private boolean useAstronomicalChatzosForOtherZmanim = false; 181 182 /** 183 * Is astronomical <em>chatzos</em> used for <em>zmanim</em> calculations besides <em>chatzos</em> itself for enhanced 184 * accuracy. For example as the day is lengthening (as we approach spring season), the second half of the day is longer than 185 * the first and astronomical <em>chatzos</em> would be a drop earlier than half of the time between sunrise and sunset. 186 * Conversely, the second half of the day would be shorter in the fall season as the days start getting shorter. 187 * 188 * @todo In the future, if this is set to true, the following may change to enhance accuracy. {@link #getSofZmanShmaGRA() 189 * <em>Sof zman Shma</em> GRA} would be calculated as 3 <em>shaaos zmaniyos</em> after sunrise, but the <em>shaaos 190 * zmaniyos</em> would be calculated a a 6th of the time between sunrise and <em>chatzos</em>, as opposed to a 12th of the 191 * time between sunrise and sunset. {@link #getMinchaGedola() <em>mincha gedola</em>} will be calculated as half a 192 * <em>shaah zmanis</em> of afternoon hours (a 6th of the time between <em>chatzos</em> and sunset after astronomical 193 * <em>chatzos</em> as opposed to 6.5 <em>shaaos zmaniyos</em> after sunrise. {@link #getPlagHamincha() <em>Plag 194 * hamincha</em>} would be calculated as 4.75 <em>shaaos zmaniyos</em> after astronomical <em>chatzos</em> as opposed to 10.75 195 * <em>shaaos zmaniyos</em> after sunrise. Etc. 196 * 197 * @return if the use of astronomical <em>chatzos</em> is active. 198 * @see #useAstronomicalChatzosForOtherZmanim 199 * @see #setUseAstronomicalChatzosForOtherZmanim(boolean) 200 * @see #useAstronomicalChatzos 201 * @see #setUseAstronomicalChatzos(boolean) 202 */ 203 public boolean isUseAstronomicalChatzosForOtherZmanim() { 204 return useAstronomicalChatzosForOtherZmanim; 205 } 206 207 /** 208 * Sets if astronomical <em>chatzos</em> should be used in calculations of other <em>zmanim</em> for enhanced accuracy. 209 * @param useAstronomicalChatzosForOtherZmanim set to true to use astronomical in <em>chatzos</em> in <em>zmanim</em> calculations. 210 * @see #useAstronomicalChatzos 211 * @see #isUseAstronomicalChatzos() 212 */ 213 public void setUseAstronomicalChatzosForOtherZmanim(boolean useAstronomicalChatzosForOtherZmanim) { 214 this.useAstronomicalChatzosForOtherZmanim = useAstronomicalChatzosForOtherZmanim; 215 } 216 217 /** 218 * The zenith of 16.1° below geometric zenith (90°). This calculation is used for determining <em>alos</em> 219 * (dawn) and <em>tzais</em> (nightfall) in some opinions. It is based on the calculation that the time between dawn 220 * and sunrise (and sunset to nightfall) is 72 minutes, the time that is takes to walk 4 <em>mil</em> at 18 minutes 221 * a mil (<em><a href="https://en.wikipedia.org/wiki/Maimonides">Rambam</a></em> and others). The sun's position at 222 * 72 minutes before {@link #getSunrise sunrise} in Jerusalem <a href= 223 * "https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/">around the equinox / equilux</a> is 224 * 16.1° below {@link #GEOMETRIC_ZENITH geometric zenith}. 225 * 226 * @see #getAlosHashachar() 227 * @see ComplexZmanimCalendar#getAlos16Point1Degrees() 228 * @see ComplexZmanimCalendar#getTzais16Point1Degrees() 229 * @see ComplexZmanimCalendar#getSofZmanShmaMGA16Point1Degrees() 230 * @see ComplexZmanimCalendar#getSofZmanTfilaMGA16Point1Degrees() 231 * @see ComplexZmanimCalendar#getMinchaGedola16Point1Degrees() 232 * @see ComplexZmanimCalendar#getMinchaKetana16Point1Degrees() 233 * @see ComplexZmanimCalendar#getPlagHamincha16Point1Degrees() 234 * @see ComplexZmanimCalendar#getPlagAlos16Point1ToTzaisGeonim7Point083Degrees() 235 * @see ComplexZmanimCalendar#getSofZmanShmaAlos16Point1ToSunset() 236 */ 237 protected static final double ZENITH_16_POINT_1 = GEOMETRIC_ZENITH + 16.1; 238 239 /** 240 * The zenith of 8.5° below geometric zenith (90°). This calculation is used for calculating <em>alos</em> 241 * (dawn) and <em>tzais</em> (nightfall) in some opinions. This calculation is based on the position of the sun 36 242 * minutes after {@link #getSunset sunset} in Jerusalem <a href= 243 * "https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/">around the equinox / equilux</a>, which 244 * is 8.5° below {@link #GEOMETRIC_ZENITH geometric zenith}. The <em><a href= 245 * "https://www.worldcat.org/oclc/29283612">Ohr Meir</a></em> considers this the time that 3 small stars are visible, 246 * which is later than the required 3 medium stars. 247 * 248 * @see #getTzais() 249 * @see ComplexZmanimCalendar#getTzaisGeonim8Point5Degrees() 250 */ 251 protected static final double ZENITH_8_POINT_5 = GEOMETRIC_ZENITH + 8.5; 252 253 /** 254 * The default <em>Shabbos</em> candle lighting offset is 18 minutes. This can be changed via the 255 * {@link #setCandleLightingOffset(double)} and retrieved by the {@link #getCandleLightingOffset()}. 256 */ 257 private double candleLightingOffset = 18; 258 259 /** 260 * This method will return {@link #getSeaLevelSunrise() sea level sunrise} if {@link #isUseElevation()} is false (the 261 * default), or elevation adjusted {@link AstronomicalCalendar#getSunrise()} if it is true. This allows relevant <em>zmanim</em> 262 * in this and extending classes (such as the {@link ComplexZmanimCalendar}) to automatically adjust to the elevation setting. 263 * 264 * @return {@link #getSeaLevelSunrise()} if {@link #isUseElevation()} is false (the default), or elevation adjusted 265 * {@link AstronomicalCalendar#getSunrise()} if it is true. 266 * @see com.kosherjava.zmanim.AstronomicalCalendar#getSunrise() 267 */ 268 protected Date getElevationAdjustedSunrise() { 269 if(isUseElevation()) { 270 return super.getSunrise(); 271 } 272 return getSeaLevelSunrise(); 273 } 274 275 /** 276 * This method will return {@link #getSeaLevelSunrise() sea level sunrise} if {@link #isUseElevation()} is false (the default), 277 * or elevation adjusted {@link AstronomicalCalendar#getSunrise()} if it is true. This allows relevant <em>zmanim</em> 278 * in this and extending classes (such as the {@link ComplexZmanimCalendar}) to automatically adjust to the elevation setting. 279 * 280 * @return {@link #getSeaLevelSunset()} if {@link #isUseElevation()} is false (the default), or elevation adjusted 281 * {@link AstronomicalCalendar#getSunset()} if it is true. 282 * @see com.kosherjava.zmanim.AstronomicalCalendar#getSunset() 283 */ 284 protected Date getElevationAdjustedSunset() { 285 if(isUseElevation()) { 286 return super.getSunset(); 287 } 288 return getSeaLevelSunset(); 289 } 290 291 /** 292 * A method that returns <em>tzais</em> (nightfall) when the sun is {@link #ZENITH_8_POINT_5 8.5°} below the 293 * {@link #GEOMETRIC_ZENITH geometric horizon} (90°) after {@link #getSunset sunset}, a time that Rabbi Meir 294 * Posen in his the <em><a href="https://www.worldcat.org/oclc/29283612">Ohr Meir</a></em> calculated that 3 small 295 * stars are visible, which is later than the required 3 medium stars. See the {@link #ZENITH_8_POINT_5} constant. 296 * 297 * @see #ZENITH_8_POINT_5 298 * 299 * @return The <code>Date</code> of nightfall. If the calculation can't be computed such as northern and southern 300 * locations even south of the Arctic Circle and north of the Antarctic Circle where the sun may not reach 301 * low enough below the horizon for this calculation, a <code>null</code> will be returned. See detailed 302 * explanation on top of the {@link AstronomicalCalendar} documentation. 303 * @see #ZENITH_8_POINT_5 304 * ComplexZmanimCalendar#getTzaisGeonim8Point5Degrees() that returns an identical time to this generic <em>tzais</em> 305 */ 306 public Date getTzais() { 307 return getSunsetOffsetByDegrees(ZENITH_8_POINT_5); 308 } 309 310 /** 311 * Returns <em>alos</em> (dawn) based on the time when the sun is {@link #ZENITH_16_POINT_1 16.1°} below the 312 * eastern {@link #GEOMETRIC_ZENITH geometric horizon} before {@link #getSunrise sunrise}. This is based on the 313 * calculation that the time between dawn and sunrise (and sunset to nightfall) is 72 minutes, the time that is 314 * takes to walk 4 <em>mil</em> at 18 minutes a mil (<em><a href="https://en.wikipedia.org/wiki/Maimonides" 315 * >Rambam</a></em> and others). The sun's position at 72 minutes before {@link #getSunrise sunrise} in Jerusalem 316 * on the <a href="https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/">around the equinox / 317 * equilux</a> is 16.1° below {@link #GEOMETRIC_ZENITH}. 318 * 319 * @see #ZENITH_16_POINT_1 320 * @see ComplexZmanimCalendar#getAlos16Point1Degrees() 321 * 322 * @return The <code>Date</code> of dawn. If the calculation can't be computed such as northern and southern 323 * locations even south of the Arctic Circle and north of the Antarctic Circle where the sun may not reach 324 * low enough below the horizon for this calculation, a <code>null</code> will be returned. See detailed 325 * explanation on top of the {@link AstronomicalCalendar} documentation. 326 */ 327 public Date getAlosHashachar() { 328 return getSunriseOffsetByDegrees(ZENITH_16_POINT_1); 329 } 330 331 /** 332 * Method to return <em>alos</em> (dawn) calculated using 72 minutes before {@link #getSunrise() sunrise} or 333 * {@link #getSeaLevelSunrise() sea level sunrise} (depending on the {@link #isUseElevation()} setting). This time 334 * is based on the time to walk the distance of 4 <em>Mil</em> at 18 minutes a <em>Mil</em>. The 72 minute time (but 335 * not the concept of fixed minutes) is based on the opinion that the time of the <em>Neshef</em> (twilight between 336 * dawn and sunrise) does not vary by the time of year or location but depends on the time it takes to walk the 337 * distance of 4 <em>Mil</em>. 338 * 339 * @return the <code>Date</code> representing the time. If the calculation can't be computed such as in the Arctic 340 * Circle where there is at least one day a year where the sun does not rise, and one where it does not set, 341 * a <code>null</code> will be returned. See detailed explanation on top of the {@link AstronomicalCalendar} 342 * documentation. 343 */ 344 public Date getAlos72() { 345 return getTimeOffset(getElevationAdjustedSunrise(), -72 * MINUTE_MILLIS); 346 } 347 348 /** 349 * This method returns {@link #getSunTransit() Astronomical <em>chatzos</em>} if the 350 * {@link com.kosherjava.zmanim.util.AstronomicalCalculator calculator} class used supports it and 351 * {@link #isUseAstronomicalChatzos() isUseAstronomicalChatzos()} is set to <em>true</em> or the {@link #getChatzosAsHalfDay() 352 * halfway point between sunrise and sunset} if it does not support it or it is not configured to use it. There are currently 353 * two {@link com.kosherjava.zmanim.util.AstronomicalCalculator calculators} available in the API, the default {@link 354 * com.kosherjava.zmanim.util.NOAACalculator NOAA calculator} and the {@link com.kosherjava.zmanim.util.SunTimesCalculator USNO 355 * calculator}. The USNO calculator calculates <em>chatzos</em> as halfway between sunrise and sunset (identical to six <em>shaaos 356 * zmaniyos</em> after sunrise), while the NOAACalculator calculates it more accurately as {@link #getSunTransit() astronomical 357 * <em>chatzos</em>}. See <a href="https://kosherjava.com/2020/07/02/definition-of-chatzos/">The Definition of <em>Chatzos</em></a> 358 * for a detailed explanation of the ways to calculate <em>Chatzos</em>. Since half-day <em>chatzos</em> can be <code>null</code> in 359 * the Arctic on a day when either sunrise or sunset did not happen and astronomical <em>chatzos</em> can be calculated even in that 360 * case, even if it is not configured to use astronomical <em>chatzos</em>, if half-day <em>chatzos</em> is null and astronomical 361 * <em>chatzos</em> is supported by the calculator, astronomical <em>chatzos</em> will be returned in an effort to not return a 362 * <code>null</code>. 363 * 364 * @see AstronomicalCalendar#getSunTransit() 365 * @see #getChatzosAsHalfDay() 366 * @see #isUseAstronomicalChatzos() 367 * @see #setUseAstronomicalChatzos(boolean) 368 * @return the <code>Date</code> of <em>chatzos</em>. If the calculation can't be computed such as in the Arctic Circle 369 * where there is at least one day where the sun does not rise, and one where it does not set, and the calculator does not 370 * support astronomical calculations (that will never report a <code>null</code>) a <code>null</code> will be returned. 371 * See detailed explanation on top of the {@link AstronomicalCalendar} documentation. 372 */ 373 public Date getChatzos() { 374 if(useAstronomicalChatzos) { 375 return getSunTransit(); // can be null of the calculator does not support astronomical chatzos 376 } else { 377 Date halfDayChatzos = getChatzosAsHalfDay(); 378 if(halfDayChatzos == null) { 379 return getSunTransit(); // can be null if the calculator does not support astronomical chatzos 380 } else { 381 return halfDayChatzos; 382 } 383 } 384 } 385 386 /** 387 * Returns <em>chatzos</em> calculated as halfway between sunrise and sunset. Many are of the opinion opinion that 388 * <em>chatzos</em> is calculated as the the midpoint between {@link #getSeaLevelSunrise sea level sunrise} and 389 * {@link #getSeaLevelSunset sea level sunset}, despite it not being the most accurate way to calculate it. A day 390 * starting at <em>alos</em> and ending at <em>tzais</em> using the same time or degree offset will also return 391 * the same time. In reality due to lengthening or shortening of day, this is not necessarily the exact midpoint of 392 * the day, but it is very close. This method allows you to use the NOAACalculator and still calculate <em>chatzos 393 * </em> as six <em>shaaos zmaniyos</em> after sunrise. There are currently two {@link 394 * com.kosherjava.zmanim.util.AstronomicalCalculator calculators} available in the API, the {@link 395 * com.kosherjava.zmanim.util.NOAACalculator} and the {@link com.kosherjava.zmanim.util.SunTimesCalculator}. 396 * The SunTimesCalculator calculates <em>chatzos</em> as halfway between sunrise and sunset (and of six <em>shaaos 397 * zmaniyos</em>), while the NOAACalculator calculates it as astronomical <em>chatzos</em> that is slightly more 398 * accurate. This method allows you to use the NOAACalculator and still calculate <em>chatzos</em> as six <em>shaaos 399 * zmaniyos</em> after sunrise. See <a href="https://kosherjava.com/2020/07/02/definition-of-chatzos/">The Definition 400 * of <em>Chatzos</em></a> for a detailed explanation of the ways to calculate <em>Chatzos</em>. 401 * 402 * @see com.kosherjava.zmanim.util.NOAACalculator#getUTCNoon(Calendar, GeoLocation) 403 * @see com.kosherjava.zmanim.util.SunTimesCalculator#getUTCNoon(Calendar, GeoLocation) 404 * @see com.kosherjava.zmanim.util.AstronomicalCalculator#getUTCNoon(Calendar, GeoLocation) 405 * @see AstronomicalCalendar#getSunTransit(Date, Date) 406 * @see #getChatzos() 407 * @see #getSunTransit() 408 * @see #isUseAstronomicalChatzos() 409 * 410 * @return the <code>Date</code> of the latest <em>chatzos</em>. If the calculation can't be computed such 411 * as in the Arctic Circle where there is at least one day a year where the sun does not rise, and one where 412 * it does not set, a <code>null</code> will be returned. See detailed explanation on top of the 413 * {@link AstronomicalCalendar} documentation. 414 */ 415 public Date getChatzosAsHalfDay() { 416 return getSunTransit(getSeaLevelSunrise(), getSeaLevelSunset()); 417 } 418 419 /** 420 * A generic method for calculating the latest <em>zman krias shema</em> (time to recite shema in the morning) 421 * that is 3 * <em>shaos zmaniyos</em> (temporal hours) after the start of the day, calculated using the start and 422 * end of the day passed to this method. 423 * The time from the start of day to the end of day are divided into 12 <em>shaos zmaniyos</em> (temporal hours), 424 * and the latest <em>zman krias shema</em> is calculated as 3 of those <em>shaos zmaniyos</em> after the beginning of 425 * the day. As an example, passing {@link #getSunrise() sunrise} and {@link #getSunset sunset} or {@link #getSeaLevelSunrise() 426 * sea level sunrise} and {@link #getSeaLevelSunset() sea level sunset} (depending on the {@link #isUseElevation()} 427 * elevation setting) to this method will return <em>sof zman krias shema</em> according to the opinion of the 428 * <em><a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a></em>. 429 * 430 * @param startOfDay 431 * the start of day for calculating <em>zman krias shema</em>. This can be sunrise or any <em>alos</em> passed 432 * to this method. 433 * @param endOfDay 434 * the end of day for calculating <em>zman krias shema</em>. This can be sunset or any <em>tzais</em> passed to 435 * this method. 436 * @return the <code>Date</code> of the latest <em>zman shema</em> based on the start and end of day times passed to this 437 * method. If the calculation can't be computed such as in the Arctic Circle where there is at least one day 438 * a year where the sun does not rise, and one where it does not set, a <code>null</code> will be returned. See 439 * detailed explanation on top of the {@link AstronomicalCalendar} documentation. 440 */ 441 public Date getSofZmanShma(Date startOfDay, Date endOfDay) { 442 return getShaahZmanisBasedZman(startOfDay, endOfDay, 3); 443 } 444 445 /** 446 * This method returns the latest <em>zman krias shema</em> (time to recite shema in the morning) that is 3 * 447 * {@link #getShaahZmanisGra() <em>shaos zmaniyos</em>} (solar hours) after {@link #getSunrise() sunrise} or 448 * {@link #getSeaLevelSunrise() sea level sunrise} (depending on the {@link #isUseElevation()} setting), according 449 * to the <a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a>. 450 * The day is calculated from {@link #getSeaLevelSunrise() sea level sunrise} to {@link #getSeaLevelSunrise sea level 451 * sunset} or {@link #getSunrise() sunrise} to {@link #getSunset() sunset} (depending on the {@link #isUseElevation()} 452 * setting). 453 * 454 * @see #getSofZmanShma(Date, Date) 455 * @see #getShaahZmanisGra() 456 * @see #isUseElevation() 457 * @see ComplexZmanimCalendar#getSofZmanShmaBaalHatanya() 458 * @return the <code>Date</code> of the latest <em>zman shema</em> according to the GRA. If the calculation can't be 459 * computed such as in the Arctic Circle where there is at least one day a year where the sun does not rise, 460 * and one where it does not set, a <code>null</code> will be returned. See the detailed explanation on top 461 * of the {@link AstronomicalCalendar} documentation. 462 */ 463 public Date getSofZmanShmaGRA() { 464 return getSofZmanShma(getElevationAdjustedSunrise(), getElevationAdjustedSunset()); 465 } 466 467 /** 468 * This method returns the latest <em>zman krias shema</em> (time to recite shema in the morning) that is 3 * 469 * {@link #getShaahZmanisMGA() <em>shaos zmaniyos</em>} (solar hours) after {@link #getAlos72()}, according to the 470 * <a href="https://en.wikipedia.org/wiki/Avraham_Gombinern">Magen Avraham (MGA)</a>. The day is calculated 471 * from 72 minutes before {@link #getSeaLevelSunrise() sea level sunrise} to 72 minutes after {@link 472 * #getSeaLevelSunrise sea level sunset} or from 72 minutes before {@link #getSunrise() sunrise} to {@link #getSunset() 473 * sunset} (depending on the {@link #isUseElevation()} setting). 474 * 475 * @return the <code>Date</code> of the latest <em>zman shema</em>. If the calculation can't be computed such as in 476 * the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it 477 * does not set, a <code>null</code> will be returned. See detailed explanation on top of the 478 * {@link AstronomicalCalendar} documentation. 479 * @see #getSofZmanShma(Date, Date) 480 * @see ComplexZmanimCalendar#getShaahZmanis72Minutes() 481 * @see ComplexZmanimCalendar#getAlos72() 482 * @see ComplexZmanimCalendar#getSofZmanShmaMGA72Minutes() that 483 */ 484 public Date getSofZmanShmaMGA() { 485 return getSofZmanShma(getAlos72(), getTzais72()); 486 } 487 488 /** 489 * This method returns the <em>tzais</em> (nightfall) based on the opinion of <em>Rabbeinu Tam</em> that 490 * <em>tzais hakochavim</em> is calculated as 72 minutes, the time it takes to walk 4 <em>Mil</em> at 18 minutes 491 * a <em>Mil</em>. According to the <a href="https://en.wikipedia.org/wiki/Samuel_Loew">Machtzis Hashekel</a> in 492 * Orach Chaim 235:3, the <a href="https://en.wikipedia.org/wiki/Joseph_ben_Meir_Teomim">Pri Megadim</a> in Orach 493 * Chaim 261:2 (see the Biur Halacha) and others (see Hazmanim Bahalacha 17:3 and 17:5) the 72 minutes are standard 494 * clock minutes any time of the year in any location. Depending on the {@link #isUseElevation()} setting) a 72 495 * minute offset from either {@link #getSunset() sunset} or {@link #getSeaLevelSunset() sea level sunset} is used. 496 * 497 * @see ComplexZmanimCalendar#getTzais16Point1Degrees() 498 * @return the <code>Date</code> representing 72 minutes after sunset. If the calculation can't be 499 * computed such as in the Arctic Circle where there is at least one day a year where the sun does not rise, 500 * and one where it does not set, a <code>null</code> will be returned See detailed explanation on top of the 501 * {@link AstronomicalCalendar} documentation. 502 */ 503 public Date getTzais72() { 504 return getTimeOffset(getElevationAdjustedSunset(), 72 * MINUTE_MILLIS); 505 } 506 507 /** 508 * A method to return candle lighting time, calculated as {@link #getCandleLightingOffset()} minutes before 509 * {@link #getSeaLevelSunset() sea level sunset}. This will return the time for any day of the week, since it can be 510 * used to calculate candle lighting time for <em>Yom Tov</em> (mid-week holidays) as well. Elevation adjustments 511 * are intentionally not performed by this method, but you can calculate it by passing the elevation adjusted sunset 512 * to {@link #getTimeOffset(Date, long)}. 513 * 514 * @return candle lighting time. If the calculation can't be computed such as in the Arctic Circle where there is at 515 * least one day a year where the sun does not rise, and one where it does not set, a <code>null</code> will 516 * be returned. See detailed explanation on top of the {@link AstronomicalCalendar} documentation. 517 * 518 * @see #getSeaLevelSunset() 519 * @see #getCandleLightingOffset() 520 * @see #setCandleLightingOffset(double) 521 */ 522 public Date getCandleLighting() { 523 return getTimeOffset(getSeaLevelSunset(), -getCandleLightingOffset() * MINUTE_MILLIS); 524 } 525 526 /** 527 * A generic method for calculating the latest <em>zman tfilah</em> (time to recite the morning prayers) 528 * that is 4 * <em>shaos zmaniyos</em> (temporal hours) after the start of the day, calculated using the start and 529 * end of the day passed to this method. 530 * The time from the start of day to the end of day are divided into 12 <em>shaos zmaniyos</em> (temporal hours), 531 * and <em>sof zman tfila</em> is calculated as 4 of those <em>shaos zmaniyos</em> after the beginning of the day. 532 * As an example, passing {@link #getSunrise() sunrise} and {@link #getSunset sunset} or {@link #getSeaLevelSunrise() 533 * sea level sunrise} and {@link #getSeaLevelSunset() sea level sunset} (depending on the {@link #isUseElevation()} 534 * elevation setting) to this method will return <em>zman tfilah</em> according to the opinion of the <em><a href= 535 * "https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a></em>. 536 * 537 * @param startOfDay 538 * the start of day for calculating <em>zman tfilah</em>. This can be sunrise or any <em>alos</em> passed 539 * to this method. 540 * @param endOfDay 541 * the end of day for calculating <em>zman tfilah</em>. This can be sunset or any <em>tzais</em> passed 542 * to this method. 543 * @return the <code>Date</code> of the latest <em>zman tfilah</em> based on the start and end of day times passed 544 * to this method. If the calculation can't be computed such as in the Arctic Circle where there is at least 545 * one day a year where the sun does not rise, and one where it does not set, a <code>null</code> will be 546 * returned. See detailed explanation on top of the {@link AstronomicalCalendar} documentation. 547 */ 548 public Date getSofZmanTfila(Date startOfDay, Date endOfDay) { 549 return getShaahZmanisBasedZman(startOfDay, endOfDay, 4); 550 } 551 552 /** 553 * This method returns the latest <em>zman tfila</em> (time to recite shema in the morning) that is 4 * 554 * {@link #getShaahZmanisGra() <em>shaos zmaniyos</em> }(solar hours) after {@link #getSunrise() sunrise} or 555 * {@link #getSeaLevelSunrise() sea level sunrise} (depending on the {@link #isUseElevation()} setting), according 556 * to the <a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a>. 557 * The day is calculated from {@link #getSeaLevelSunrise() sea level sunrise} to {@link #getSeaLevelSunrise sea level 558 * sunset} or {@link #getSunrise() sunrise} to {@link #getSunset() sunset} (depending on the {@link #isUseElevation()} 559 * setting). 560 * 561 * @see #getSofZmanTfila(Date, Date) 562 * @see #getShaahZmanisGra() 563 * @see ComplexZmanimCalendar#getSofZmanTfilaBaalHatanya() 564 * @return the <code>Date</code> of the latest <em>zman tfilah</em>. If the calculation can't be computed such as in 565 * the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it 566 * does not set, a <code>null</code> will be returned. See detailed explanation on top of the 567 * {@link AstronomicalCalendar} documentation. 568 */ 569 public Date getSofZmanTfilaGRA() { 570 return getSofZmanTfila(getElevationAdjustedSunrise(), getElevationAdjustedSunset()); 571 } 572 573 /** 574 * This method returns the latest <em>zman tfila</em> (time to recite shema in the morning) that is 4 * 575 * {@link #getShaahZmanisMGA() <em>shaos zmaniyos</em>} (solar hours) after {@link #getAlos72()}, according to the 576 * <em><a href="https://en.wikipedia.org/wiki/Avraham_Gombinern">Magen Avraham (MGA)</a></em>. The day is calculated 577 * from 72 minutes before {@link #getSeaLevelSunrise() sea level sunrise} to 72 minutes after {@link 578 * #getSeaLevelSunrise sea level sunset} or from 72 minutes before {@link #getSunrise() sunrise} to {@link #getSunset() 579 * sunset} (depending on the {@link #isUseElevation()} setting). 580 * 581 * @return the <code>Date</code> of the latest <em>zman tfila</em>. If the calculation can't be computed such as in 582 * the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it 583 * does not set), a <code>null</code> will be returned. See detailed explanation on top of the 584 * {@link AstronomicalCalendar} documentation. 585 * @see #getSofZmanTfila(Date, Date) 586 * @see #getShaahZmanisMGA() 587 * @see #getAlos72() 588 */ 589 public Date getSofZmanTfilaMGA() { 590 return getSofZmanTfila(getAlos72(), getTzais72()); 591 } 592 593 /** 594 * A generic method for calculating the latest <em>mincha gedola</em> (the earliest time to recite the <em>mincha1</em> 595 * prayers) that is 6.5 * <em>shaos zmaniyos</em> (temporal hours) after the start of the day, calculated using the start 596 * and end of the day passed to this method. The time from the start of day to the end of day are divided into 12 597 * <em>shaos zmaniyos</em> (temporal hours), and <em>mincha gedola</em> is calculated as 6.5 of those <em>shaos 598 * zmaniyos</em> after the beginning of the day. As an example, passing {@link #getSunrise() sunrise} and {@link #getSunset 599 * sunset} or {@link #getSeaLevelSunrise() sea level sunrise} and {@link #getSeaLevelSunset() sea level sunset} (depending 600 * on the {@link #isUseElevation()} elevation setting) to this method will return <em>mincha gedola</em> according to the 601 * opinion of the <em><a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a></em>. Alternatively, this method uses {@link 602 * #isUseAstronomicalChatzosForOtherZmanim()} to control if the time is based on 6.5 <em>sha'os zmaniyos</em> into the day 603 * mentioned above, or as half an hour <em>zmaniyos</em> based on the second half of the day after <em>chatzos</em> ({@link 604 * #getSunTransit() astronomical <em>chatzos</em>} if supported by the {@link AstronomicalCalculator calculator} and {@link 605 * #isUseAstronomicalChatzos() configured} or {@link #getChatzosAsHalfDay() <em>chatzos</em> as half a day} if not. 606 * 607 * @param startOfDay 608 * the start of day for calculating <em>Mincha gedola</em>. This can be sunrise or any <em>alos</em> passed 609 * to this method. 610 * @param endOfDay 611 * the end of day for calculating <em>Mincha gedola</em>. This can be sunset or any <em>tzais</em> passed 612 * to this method. 613 * @return the <code>Date</code> of the time of <em>Mincha gedola</em> based on the start and end of day times 614 * passed to this method. If the calculation can't be computed such as in the Arctic Circle where there is 615 * at least one day a year where the sun does not rise, and one where it does not set, a <code>null</code> will 616 * be returned. See detailed explanation on top of the {@link AstronomicalCalendar} documentation. 617 * @see #getSunTransit() 618 * @see #getChatzosAsHalfDay() 619 * @see #getChatzos() 620 * @see #isUseAstronomicalChatzos() 621 * @see #isUseAstronomicalChatzosForOtherZmanim() 622 */ 623 public Date getMinchaGedola(Date startOfDay, Date endOfDay) { 624 if(isUseAstronomicalChatzosForOtherZmanim()) { 625 return getHalfDayBasedZman(getChatzos(), endOfDay, 0.5); 626 } else { 627 return getShaahZmanisBasedZman(startOfDay, endOfDay, 6.5); 628 } 629 } 630 631 /** 632 * This method returns the latest <em>mincha gedola</em>,the earliest time one can pray <em>mincha</em> that is 6.5 * 633 * {@link #getShaahZmanisGra() <em>shaos zmaniyos</em>} (solar hours) after {@link #getSunrise() sunrise} or 634 * {@link #getSeaLevelSunrise() sea level sunrise} (depending on the {@link #isUseElevation()} setting), according 635 * to the <em><a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a></em>. <em>Mincha gedola</em> is the earliest 636 * time one can pray <em>mincha</em>. The Ramba"m is of the opinion that it is better to delay <em>mincha</em> until 637 * {@link #getMinchaKetana() <em>mincha ketana</em>} while the <em>Ra"sh, Tur, GRA</em> and others are of the 638 * opinion that <em>mincha</em> can be prayed <em>lechatchila</em> starting at <em>mincha gedola</em>. 639 * The day is calculated from {@link #getSeaLevelSunrise() sea level sunrise} to {@link #getSeaLevelSunrise sea level 640 * sunset} or {@link #getSunrise() sunrise} to {@link #getSunset() sunset} (depending on the {@link #isUseElevation()} 641 * setting). 642 * @todo Consider adjusting this to calculate the time as half an hour <em>zmaniyos</em> after either {@link 643 * #getSunTransit() astronomical <em>chatzos</em>} or {@link #getChatzosAsHalfDay() <em>chatzos</em> as half a day} 644 * for {@link AstronomicalCalculator calculators} that support it, based on {@link #isUseAstronomicalChatzos()}. 645 * 646 * @see #getMinchaGedola(Date, Date) 647 * @see #getShaahZmanisGra() 648 * @see #getMinchaKetana() 649 * @see ComplexZmanimCalendar#getMinchaGedolaBaalHatanya() 650 * @return the <code>Date</code> of the time of mincha gedola. If the calculation can't be computed such as in the 651 * Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does 652 * not set, a <code>null</code> will be returned. See detailed explanation on top of the 653 * {@link AstronomicalCalendar} documentation. 654 */ 655 public Date getMinchaGedola() { 656 if(isUseAstronomicalChatzosForOtherZmanim()) { 657 return getHalfDayBasedZman(getChatzos(), getSunset(), 0.5); 658 } else { 659 return getMinchaGedola(getElevationAdjustedSunrise(), getElevationAdjustedSunset()); 660 } 661 } 662 663 /** 664 * A generic method for calculating <em>samuch lemincha ketana</em>, / near <em>mincha ketana</em> time that is half 665 * an hour before {@link #getMinchaKetana(Date, Date)} or 9 * <em>shaos zmaniyos</em> (temporal hours) after the 666 * start of the day, calculated using the start and end of the day passed to this method. 667 * The time from the start of day to the end of day are divided into 12 <em>shaos zmaniyos</em> (temporal hours), and 668 * <em>samuch lemincha ketana</em> is calculated as 9 of those <em>shaos zmaniyos</em> after the beginning of the day. 669 * For example, passing {@link #getSunrise() sunrise} and {@link #getSunset sunset} or {@link #getSeaLevelSunrise() sea 670 * level sunrise} and {@link #getSeaLevelSunset() sea level sunset} (depending on the {@link #isUseElevation()} elevation 671 * setting) to this method will return <em>samuch lemincha ketana</em> according to the opinion of the 672 * <a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a>. 673 * 674 * @param startOfDay 675 * the start of day for calculating <em>samuch lemincha ketana</em>. This can be sunrise or any <em>alos</em> 676 * passed to to this method. 677 * @param endOfDay 678 * the end of day for calculating <em>samuch lemincha ketana</em>. This can be sunset or any <em>tzais</em> 679 * passed to this method. 680 * @return the <code>Date</code> of the time of <em>Mincha ketana</em> based on the start and end of day times 681 * passed to this method. If the calculation can't be computed such as in the Arctic Circle where there is 682 * at least one day a year where the sun does not rise, and one where it does not set, a <code>null</code> will 683 * be returned. See detailed explanation on top of the {@link AstronomicalCalendar} documentation. 684 * 685 * @see ComplexZmanimCalendar#getSamuchLeMinchaKetanaGRA() 686 * @see ComplexZmanimCalendar#getSamuchLeMinchaKetana16Point1Degrees() 687 * @see ComplexZmanimCalendar#getSamuchLeMinchaKetana72Minutes() 688 */ 689 public Date getSamuchLeMinchaKetana(Date startOfDay, Date endOfDay) { 690 return getShaahZmanisBasedZman(startOfDay, endOfDay, 9); 691 } 692 693 /** 694 * A generic method for calculating <em>mincha ketana</em>, (the preferred time to recite the mincha prayers in 695 * the opinion of the <em><a href="https://en.wikipedia.org/wiki/Maimonides">Rambam</a></em> and others) that is 696 * 9.5 * <em>shaos zmaniyos</em> (temporal hours) after the start of the day, calculated using the start and end 697 * of the day passed to this method. 698 * The time from the start of day to the end of day are divided into 12 <em>shaos zmaniyos</em> (temporal hours), and 699 * <em>mincha ketana</em> is calculated as 9.5 of those <em>shaos zmaniyos</em> after the beginning of the day. As an 700 * example, passing {@link #getSunrise() sunrise} and {@link #getSunset sunset} or {@link #getSeaLevelSunrise() sea 701 * level sunrise} and {@link #getSeaLevelSunset() sea level sunset} (depending on the {@link #isUseElevation()} 702 * elevation setting) to this method will return <em>mincha ketana</em> according to the opinion of the 703 * <a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a>. 704 * 705 * @param startOfDay 706 * the start of day for calculating <em>Mincha ketana</em>. This can be sunrise or any <em>alos</em> passed 707 * to this method. 708 * @param endOfDay 709 * the end of day for calculating <em>Mincha ketana</em>. This can be sunset or any <em>tzais</em> passed to 710 * this method. 711 * @return the <code>Date</code> of the time of <em>Mincha ketana</em> based on the start and end of day times 712 * passed to this method. If the calculation can't be computed such as in the Arctic Circle where there is 713 * at least one day a year where the sun does not rise, and one where it does not set, a <code>null</code> will 714 * be returned. See detailed explanation on top of the {@link AstronomicalCalendar} documentation. 715 */ 716 public Date getMinchaKetana(Date startOfDay, Date endOfDay) { 717 return getShaahZmanisBasedZman(startOfDay, endOfDay, 9.5); 718 } 719 720 /** 721 * This method returns <em>mincha ketana</em>,the preferred earliest time to pray <em>mincha</em> in the 722 * opinion of the <em><a href="https://en.wikipedia.org/wiki/Maimonides">Rambam</a></em> and others, that is 9.5 723 * * {@link #getShaahZmanisGra() <em>shaos zmaniyos</em>} (solar hours) after {@link #getSunrise() sunrise} or 724 * {@link #getSeaLevelSunrise() sea level sunrise} (depending on the {@link #isUseElevation()} setting), according 725 * to the <a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a>. For more information on this see the 726 * documentation on {@link #getMinchaGedola() <em>mincha gedola</em>}. 727 * The day is calculated from {@link #getSeaLevelSunrise() sea level sunrise} to {@link #getSeaLevelSunrise sea level 728 * sunset} or {@link #getSunrise() sunrise} to {@link #getSunset() sunset} (depending on the {@link #isUseElevation()} 729 * setting. 730 * 731 * @see #getMinchaKetana(Date, Date) 732 * @see #getShaahZmanisGra() 733 * @see #getMinchaGedola() 734 * @see ComplexZmanimCalendar#getMinchaKetanaBaalHatanya() 735 * @return the <code>Date</code> of the time of mincha ketana. If the calculation can't be computed such as in the 736 * Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does 737 * not set, a <code>null</code> will be returned. See detailed explanation on top of the 738 * {@link AstronomicalCalendar} documentation. 739 */ 740 public Date getMinchaKetana() { 741 return getMinchaKetana(getElevationAdjustedSunrise(), getElevationAdjustedSunset()); 742 } 743 744 /** 745 * A generic method for calculating <em>plag hamincha</em> (the earliest time that Shabbos can be started) that is 746 * 10.75 hours after the start of the day, (or 1.25 hours before the end of the day) based on the start and end of 747 * the day passed to the method. 748 * The time from the start of day to the end of day are divided into 12 <em>shaos zmaniyos</em> (temporal hours), and 749 * <em>plag hamincha</em> is calculated as 10.75 of those <em>shaos zmaniyos</em> after the beginning of the day. As an 750 * example, passing {@link #getSunrise() sunrise} and {@link #getSunset sunset} or {@link #getSeaLevelSunrise() sea level 751 * sunrise} and {@link #getSeaLevelSunset() sea level sunset} (depending on the {@link #isUseElevation()} elevation 752 * setting) to this method will return <em>plag mincha</em> according to the opinion of the 753 * <em><a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a></em>. 754 * 755 * @param startOfDay 756 * the start of day for calculating plag. This can be sunrise or any <em>alos</em> passed to this method. 757 * @param endOfDay 758 * the end of day for calculating plag. This can be sunset or any <em>tzais</em> passed to this method. 759 * @return the <code>Date</code> of the time of <em>plag hamincha</em> based on the start and end of day times 760 * passed to this method. If the calculation can't be computed such as in the Arctic Circle where there is 761 * at least one day a year where the sun does not rise, and one where it does not set, a <code>null</code> 762 * will be returned. See detailed explanation on top of the {@link AstronomicalCalendar} documentation. 763 */ 764 public Date getPlagHamincha(Date startOfDay, Date endOfDay) { 765 return getShaahZmanisBasedZman(startOfDay, endOfDay, 10.75); 766 } 767 768 /** 769 * This method returns <em>plag hamincha</em>, that is 10.75 * {@link #getShaahZmanisGra() <em>shaos zmaniyos</em>} 770 * (solar hours) after {@link #getSunrise() sunrise} or {@link #getSeaLevelSunrise() sea level sunrise} (depending on 771 * the {@link #isUseElevation()} setting), according to the <em><a href="https://en.wikipedia.org/wiki/Vilna_Gaon" 772 * >GRA</a></em>. Plag hamincha is the earliest time that <em>Shabbos</em> can be started. 773 * The day is calculated from {@link #getSeaLevelSunrise() sea level sunrise} to {@link #getSeaLevelSunrise sea level 774 * sunset} or {@link #getSunrise() sunrise} to {@link #getSunset() sunset} (depending on the {@link #isUseElevation()} 775 * 776 * @see #getPlagHamincha(Date, Date) 777 * @see ComplexZmanimCalendar#getPlagHaminchaBaalHatanya() 778 * @return the <code>Date</code> of the time of <em>plag hamincha</em>. If the calculation can't be computed such as 779 * in the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it 780 * does not set, a <code>null</code> will be returned. See detailed explanation on top of the 781 * {@link AstronomicalCalendar} documentation. 782 */ 783 public Date getPlagHamincha() { 784 return getPlagHamincha(getElevationAdjustedSunrise(), getElevationAdjustedSunset()); 785 } 786 787 /** 788 * A method that returns a <em>shaah zmanis</em> ({@link #getTemporalHour(Date, Date) temporal hour}) according to 789 * the opinion of the <em><a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a></em>. This calculation divides 790 * the day based on the opinion of the <em>GRA</em> that the day runs from from {@link #getSeaLevelSunrise() sea 791 * level sunrise} to {@link #getSeaLevelSunrise sea level sunset} or {@link #getSunrise() sunrise} to 792 * {@link #getSunset() sunset} (depending on the {@link #isUseElevation()} setting). The day is split into 12 equal 793 * parts with each one being a <em>shaah zmanis</em>. This method is similar to {@link #getTemporalHour}, but can 794 * account for elevation. 795 * 796 * @return the <code>long</code> millisecond length of a <em>shaah zmanis</em> calculated from sunrise to sunset. 797 * If the calculation can't be computed such as in the Arctic Circle where there is at least one day a year 798 * where the sun does not rise, and one where it does not set, {@link Long#MIN_VALUE} will be returned. See 799 * detailed explanation on top of the {@link AstronomicalCalendar} documentation. 800 * @see #getTemporalHour(Date, Date) 801 * @see #getSeaLevelSunrise() 802 * @see #getSeaLevelSunset() 803 * @see ComplexZmanimCalendar#getShaahZmanisBaalHatanya() 804 */ 805 public long getShaahZmanisGra() { 806 return getTemporalHour(getElevationAdjustedSunrise(), getElevationAdjustedSunset()); 807 } 808 809 /** 810 * A method that returns a <em>shaah zmanis</em> (temporal hour) according to the opinion of the <em><a href= 811 * "https://en.wikipedia.org/wiki/Avraham_Gombinern">Magen Avraham (MGA)</a></em> based on a 72 minutes <em>alos</em> 812 * and <em>tzais</em>. This calculation divides the day that runs from dawn to dusk (for <em>sof zman krias shema</em> and 813 * <em>tfila</em>). Dawn for this calculation is 72 minutes before {@link #getSunrise() sunrise} or {@link #getSeaLevelSunrise() 814 * sea level sunrise} (depending on the {@link #isUseElevation()} elevation setting) and dusk is 72 minutes after {@link 815 * #getSunset sunset} or {@link #getSeaLevelSunset() sea level sunset} (depending on the {@link #isUseElevation()} elevation 816 * setting). This day is split into 12 equal parts with each part being a <em>shaah zmanis</em>. Alternate methods of calculating 817 * a <em>shaah zmanis</em> according to the Magen Avraham (MGA) are available in the subclass {@link ComplexZmanimCalendar}. 818 * 819 * @return the <code>long</code> millisecond length of a <em>shaah zmanis</em>. If the calculation can't be computed 820 * such as in the Arctic Circle where there is at least one day a year where the sun does not rise, and one 821 * where it does not set, {@link Long#MIN_VALUE} will be returned. See detailed explanation on top of the 822 * {@link AstronomicalCalendar} documentation. 823 */ 824 public long getShaahZmanisMGA() { 825 return getTemporalHour(getAlos72(), getTzais72()); 826 } 827 828 /** 829 * Default constructor will set a default {@link GeoLocation#GeoLocation()}, a default 830 * {@link AstronomicalCalculator#getDefault() AstronomicalCalculator} and default the calendar to the current date. 831 * 832 * @see AstronomicalCalendar#AstronomicalCalendar() 833 */ 834 public ZmanimCalendar() { 835 super(); 836 } 837 838 /** 839 * A constructor that takes a {@link GeoLocation} as a parameter. 840 * 841 * @param location 842 * the location 843 */ 844 public ZmanimCalendar(GeoLocation location) { 845 super(location); 846 } 847 848 /** 849 * A method to get the offset in minutes before {@link AstronomicalCalendar#getSeaLevelSunset() sea level sunset} which 850 * is used in calculating candle lighting time. The default time used is 18 minutes before sea level sunset. Some 851 * calendars use 15 minutes, while the custom in Jerusalem is to use a 40 minute offset. Please check the local custom 852 * for candle lighting time. 853 * 854 * @return Returns the currently set candle lighting offset in minutes. 855 * @see #getCandleLighting() 856 * @see #setCandleLightingOffset(double) 857 */ 858 public double getCandleLightingOffset() { 859 return candleLightingOffset; 860 } 861 862 /** 863 * A method to set the offset in minutes before {@link AstronomicalCalendar#getSeaLevelSunset() sea level sunset} that is 864 * used in calculating candle lighting time. The default time used is 18 minutes before sunset. Some calendars use 15 865 * minutes, while the custom in Jerusalem is to use a 40 minute offset. 866 * 867 * @param candleLightingOffset 868 * The candle lighting offset to set in minutes. 869 * @see #getCandleLighting() 870 * @see #getCandleLightingOffset() 871 */ 872 public void setCandleLightingOffset(double candleLightingOffset) { 873 this.candleLightingOffset = candleLightingOffset; 874 } 875 876 /** 877 * This is a utility method to determine if the current Date (date-time) passed in has a <em>melacha</em> (work) prohibition. 878 * Since there are many opinions on the time of <em>tzais</em>, the <em>tzais</em> for the current day has to be passed to this 879 * class. Sunset is the classes current day's {@link #getElevationAdjustedSunset() elevation adjusted sunset} that observes the 880 * {@link #isUseElevation()} settings. The {@link JewishCalendar#getInIsrael()} will be set by the inIsrael parameter. 881 * 882 * @param currentTime the current time 883 * @param tzais the time of tzais 884 * @param inIsrael whether to use Israel holiday scheme or not 885 * 886 * @return true if <em>melacha</em> is prohibited or false if it is not. 887 * 888 * @see JewishCalendar#isAssurBemelacha() 889 * @see JewishCalendar#hasCandleLighting() 890 * @see JewishCalendar#setInIsrael(boolean) 891 */ 892 public boolean isAssurBemlacha(Date currentTime, Date tzais, boolean inIsrael) { 893 JewishCalendar jewishCalendar = new JewishCalendar(); 894 jewishCalendar.setGregorianDate(getCalendar().get(Calendar.YEAR), getCalendar().get(Calendar.MONTH), 895 getCalendar().get(Calendar.DAY_OF_MONTH)); 896 jewishCalendar.setInIsrael(inIsrael); 897 898 if(jewishCalendar.hasCandleLighting() && currentTime.compareTo(getElevationAdjustedSunset()) >= 0) { //erev shabbos, YT or YT sheni and after shkiah 899 return true; 900 } 901 902 if(jewishCalendar.isAssurBemelacha() && currentTime.compareTo(tzais) <= 0) { //is shabbos or YT and it is before tzais 903 return true; 904 } 905 906 return false; 907 } 908 909 /** 910 * A generic utility method for calculating any <em>shaah zmanis</em> (temporal hour) based <em>zman</em> with the 911 * day defined as the start and end of day (or night) and the number of <em>shaahos zmaniyos</em> passed to the 912 * method. This simplifies the code in other methods such as {@link #getPlagHamincha(Date, Date)} and cuts down on 913 * code replication. As an example, passing {@link #getSunrise() sunrise} and {@link #getSunset sunset} or {@link 914 * #getSeaLevelSunrise() sea level sunrise} and {@link #getSeaLevelSunset() sea level sunset} (depending on the 915 * {@link #isUseElevation()} elevation setting) and 10.75 hours to this method will return <em>plag mincha</em> 916 * according to the opinion of the <em><a href="https://en.wikipedia.org/wiki/Vilna_Gaon">GRA</a></em>. 917 * 918 * @param startOfDay 919 * the start of day for calculating the <em>zman</em>. This can be sunrise or any <em>alos</em> passed 920 * to this method. 921 * @param endOfDay 922 * the end of day for calculating the <em>zman</em>. This can be sunset or any <em>tzais</em> passed to 923 * this method. 924 * @param hours 925 * the number of <em>shaahos zmaniyos</em> (temporal hours) to offset from the start of day 926 * @return the <code>Date</code> of the time of <em>zman</em> with the <em>shaahos zmaniyos</em> (temporal hours) 927 * in the day offset from the start of day passed to this method. If the calculation can't be computed such 928 * as in the Arctic Circle where there is at least one day a year where the sun does not rise, and one 929 * where it does not set, a <code>null</code> will be returned. See detailed explanation on top of the 930 * {@link AstronomicalCalendar} documentation. 931 */ 932 public Date getShaahZmanisBasedZman(Date startOfDay, Date endOfDay, double hours) { 933 long shaahZmanis = getTemporalHour(startOfDay, endOfDay); 934 return getTimeOffset(startOfDay, shaahZmanis * hours); 935 } 936 937 /** 938 * A utility method that returns the percentage of a <em>shaah zmanis</em> after sunset (or before sunrise) for a given degree 939 * offset. For the <a href="https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/">equilux</a> where there 940 * is a 720-minute day, passing 16.1° for the location of Jerusalem will return about 1.2. This will work for any location 941 * or date, but will typically only be of interest at the equinox/equilux to calculate the percentage of a <em>shaah zmanis</em> 942 * for those who want to use the <a href="https://en.wikipedia.org/wiki/Abraham_Cohen_Pimentel">Minchas Cohen</a> in Ma'amar 2:4 943 * and the <a href="https://en.wikipedia.org/wiki/Hezekiah_da_Silva">Pri Chadash</a> who calculate <em>tzais</em> as a percentage 944 * of the day after sunset. While the Minchas Cohen only applies this to 72 minutes or a 1/10 of the day around the world (based 945 * on the equinox / equilux in Israel, this method allows calculations for any degrees level for any location. 946 * 947 * @param degrees 948 * the number of degrees below the horizon after sunset. 949 * @param sunset 950 * if <code>true</code> the calculation should be degrees after sunset, or if <code>false</code>, degrees before sunrise. 951 * @return the <code>double</code> percentage of a <em>sha'ah zmanis</em> for a given set of degrees below the astronomical horizon 952 * for the current calendar. If the calculation can't be computed a {@link Double#MIN_VALUE} will be returned. See detailed 953 * explanation on top of the page. 954 */ 955 public double getPercentOfShaahZmanisFromDegrees(double degrees, boolean sunset) { 956 Date seaLevelSunrise = getSeaLevelSunrise(); 957 Date seaLevelSunset = getSeaLevelSunset(); 958 Date twilight = null; 959 if(sunset) { 960 twilight = getSunsetOffsetByDegrees(GEOMETRIC_ZENITH + degrees); 961 } else { 962 twilight = getSunriseOffsetByDegrees(GEOMETRIC_ZENITH + degrees); 963 } 964 if(seaLevelSunrise == null || seaLevelSunset == null || twilight == null) { 965 return Double.MIN_VALUE; 966 } 967 double shaahZmanis = (seaLevelSunset.getTime() - seaLevelSunrise.getTime()) / 12.0; 968 long riseSetToTwilight; 969 if(sunset) { 970 riseSetToTwilight = twilight.getTime() - seaLevelSunset.getTime(); 971 } else { 972 riseSetToTwilight = seaLevelSunrise.getTime() - twilight.getTime(); 973 } 974 return riseSetToTwilight / shaahZmanis; 975 } 976 977 /** 978 * A utility method to calculate <em>zmanim</em> based on <a href="https://en.wikipedia.org/wiki/Moshe_Feinstein">Rav Moshe 979 * Feinstein</a> and others as calculated in <a href="https://en.wikipedia.org/wiki/Mesivtha_Tifereth_Jerusalem">MTJ</a>, <a href= 980 * "https://en.wikipedia.org/wiki/Mesivtha_Tifereth_Jerusalem">Yeshiva of Staten Island</a>, and Camp Yeshiva 981 * of Staten Island and other calendars. The day is split in two, from <em>alos</em> / sunrise to <em>chatzos</em>, and the 982 * second half of the day, from <em>chatzos</em> to sunset / <em>tzais</em>. Morning based times are calculated. based on the first 983 * 6 hours of the day, and afternoon times based on the second half of the day. As an example, passing 0.5, a start of 984 * <em>chatzos</em> and an end of day as sunset will return the time of <em>mincha gedola</em> GRA as half an hour <em>zmanis</em> 985 * based on the second half of the day. Some <em>zmanim</em> calculations can be based on subtracting <em>sha'os zmaniyos</em> 986 * from the end of the day, and that is supported by passing a negative hour to this method. 987 * 988 * @param startOfHalfDay 989 * The start of the half day. This would be <em>alos</em> or sunrise for morning based times such as <em>sof zman krias 990 * shema</em> and <em>chatzos</em> for afternoon based times such as <em>mincha gedola</em>. 991 * @param endOfHalfDay 992 * The end of the half day. This would be <em>chatzos</em> for morning based times such as <em>sof zman krias shema</em> 993 * and sunset or <em>tzais</em> for afternoon based times such as <em>mincha gedola</em>. 994 * @param hours 995 * The number of <em>sha'os zmaniyos</em> (hours) to offset the beginning of the first or second half of the day. For example, 996 * 3 for <em>sof zman Shma</em>, 0.5 for <em>mincha gedola</em> (half an hour after <em>chatzos</em>) and 4.75 for <em>plag 997 * hamincha</em>. If the number of hours is negative, it will subtract the number of <em>sha'os zmaniyos</em> from the end 998 * of the day. 999 * 1000 * @return the <code>Date</code> of <em>zman</em> based on calculation of the first or second half of the day. If the 1001 * calculation can't be computed such as in the Arctic Circle where there is at least one day a year where the 1002 * sun does not rise, and one where it does not set, a <code>null</code> will be returned. See detailed explanation 1003 * on top of the {@link AstronomicalCalendar} documentation. 1004 * 1005 * @see ComplexZmanimCalendar#getFixedLocalChatzos() 1006 */ 1007 public Date getHalfDayBasedZman(Date startOfHalfDay, Date endOfHalfDay, double hours) { 1008 if (startOfHalfDay == null || endOfHalfDay == null) { 1009 return null; 1010 } 1011 long shaahZmanis = getHalfDayBasedShaahZmanis(startOfHalfDay, endOfHalfDay); 1012 if(shaahZmanis == Long.MIN_VALUE) { //defensive, should not be needed 1013 return null; 1014 } 1015 if(hours >= 0) { // forward from start a day 1016 return getTimeOffset(startOfHalfDay, shaahZmanis * hours); 1017 } else { // subtract from end of day 1018 return getTimeOffset(endOfHalfDay, shaahZmanis * hours); 1019 } 1020 } 1021 1022 /** 1023 * A utility method to calculate the length of a <em>sha'ah zmanis</em> based on 1/6 of a 6 hour day. 1024 * @param startOfHalfDay The start of the half-day. This would be <em>alos</em> or sunrise for the first half of the day, 1025 * or <em>chatzos</em> for the second half of the day. 1026 * @param endOfHalfDay The end of the half-day. This would be <em>chatzos</em> for the first half of the day, or sunset or 1027 * <em>tzais</em> for the second half of the day. 1028 * @return The <code>long</code> millisecond length of a <em>shaah zmanis</em> based on 1/6 of a half-day. If the calculation 1029 * can't be computed such as in the Arctic Circle where there is at least one day a year where the sun does not rise, 1030 * and one where it does not set, {@link Long#MIN_VALUE} will be returned. See detailed explanation on top of the 1031 * {@link AstronomicalCalendar} documentation. 1032 * @see #getHalfDayBasedZman(Date, Date, double) 1033 * @see #isUseAstronomicalChatzosForOtherZmanim() 1034 */ 1035 public long getHalfDayBasedShaahZmanis(Date startOfHalfDay, Date endOfHalfDay) { 1036 if (startOfHalfDay == null || endOfHalfDay == null) { 1037 return Long.MIN_VALUE; 1038 } 1039 return (endOfHalfDay.getTime() - startOfHalfDay.getTime()) / 6; 1040 } 1041}