001/*
002 * Zmanim Java API
003 * Copyright © 2011 - 2026 Eliyahu Hershfeld
004 * Copyright © September 2002 Avrom Finkelstein
005 * Copyright © 2019 - 2022 Y Paritcher
006 * Copyright © 2026 Moshe Dicker
007 *
008 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
009 * Public License as published by the Free Software Foundation; version 2.1 of the License.
010 *
011 * This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied
012 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
013 * details.
014 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
015 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA,
016 * or connect to: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
017 */
018package com.kosherjava.zmanim.hebrewcalendar;
019
020import java.time.Duration;
021import java.time.Instant;
022import java.time.LocalDate;
023import java.time.LocalTime;
024import java.time.ZoneId;
025import java.time.ZonedDateTime;
026import java.util.Calendar; // We still use the old Calendar.WEEKDAY constants
027
028/**
029 * The JewishCalendar extends the JewishDate class and adds calendar methods.
030 * 
031 * This open source Java code was originally ported by <a href="https://www.linkedin.com/in/avromf/">Avrom Finkelstein</a>
032 * from his C++ code. It was refactored to fit the KosherJava Zmanim API with simplification of the code, enhancements
033 * and some bug fixing. The class allows setting whether the holiday and <em>parsha</em> scheme follows the Israel scheme
034 * or outside Israel scheme. The default is the outside Israel scheme.
035 * The parsha code was ported by Y. Paritcher from his <a href="https://github.com/yparitcher/libzmanim">libzmanim</a> code.
036 * 
037 * @todo Some do not belong in this class, but here is a partial list of what should still be implemented in some form:
038 * <ol>
039 * <li>Mishna yomis etc</li>
040 * </ol>
041 * 
042 * @see java.util.Date
043 * @see java.util.Calendar
044 * @author © Y. Paritcher 2019 - 2022
045 * @author © Avrom Finkelstein 2002
046 * @author © Moshe Dicker 2026
047 * @author © Eliyahu Hershfeld 2011 - 2026
048 */
049public class JewishCalendar extends JewishDate {
050        /** The 14th day of Nissan, the day before Pesach (Passover).*/
051        public static final int EREV_PESACH = 0;
052        /** The holiday of Pesach (Passover) on the 15th (and 16th out of Israel) day of Nissan.*/
053        public static final int PESACH = 1;
054        /** Chol Hamoed (interim days) of Pesach (Passover)*/
055        public static final int CHOL_HAMOED_PESACH = 2;
056        /** Pesach Sheni, the 14th day of Iyar, a minor holiday.*/
057        public static final int PESACH_SHENI = 3;
058        /** Erev Shavuos (the day before Shavuos), the 5th of Sivan*/
059        public static final int EREV_SHAVUOS = 4;
060        /** Shavuos (Pentecost), the 6th of Sivan*/
061        public static final int SHAVUOS = 5;
062        /** The fast of the 17th day of Tammuz*/
063        public static final int SEVENTEEN_OF_TAMMUZ = 6;
064        /** The fast of the 9th of Av*/
065        public static final int TISHA_BEAV = 7;
066        /** The 15th day of Av, a minor holiday*/
067        public static final int TU_BEAV = 8;
068        /** Erev Rosh Hashana (the day before Rosh Hashana), the 29th of Elul*/
069        public static final int EREV_ROSH_HASHANA = 9;
070        /** Rosh Hashana, the first and second days of Tishrei.*/
071        public static final int ROSH_HASHANA = 10;
072        /** The fast of Gedalyah, the 3rd of Tishrei.*/
073        public static final int FAST_OF_GEDALYAH = 11;
074        /** The 9th day of Tishrei, the day before of Yom Kippur.*/
075        public static final int EREV_YOM_KIPPUR = 12;
076        /** The holiday of Yom Kippur, the 10th day of Tishrei*/
077        public static final int YOM_KIPPUR = 13;
078        /** The 14th day of Tishrei, the day before of Succos/Sukkos (Tabernacles).*/
079        public static final int EREV_SUCCOS = 14;
080        /** The holiday of Succos/Sukkos (Tabernacles), the 15th (and 16th out of Israel) day of Tishrei */
081        public static final int SUCCOS = 15;
082        /** Chol Hamoed (interim days) of Succos/Sukkos (Tabernacles)*/
083        public static final int CHOL_HAMOED_SUCCOS = 16;
084        /** Hoshana Rabba, the 7th day of Succos/Sukkos that occurs on the 21st of Tishrei. */
085        public static final int HOSHANA_RABBA = 17;
086        /** Shmini Atzeres, the 8th day of Succos/Sukkos is an independent holiday that occurs on the 22nd of Tishrei. */
087        public static final int SHEMINI_ATZERES = 18;
088        /** Simchas Torah, the 9th day of Succos/Sukkos, or the second day of Shmini Atzeres that is celebrated
089         * {@link #getInIsrael() out of Israel} on the 23rd of Tishrei.
090         */
091        public static final int SIMCHAS_TORAH = 19;
092        // public static final int EREV_CHANUKAH = 20;// probably remove this
093        /** The holiday of Chanukah. 8 days starting on the 25th day Kislev.*/
094        public static final int CHANUKAH = 21;
095        /** The fast of the 10th day of Teves.*/
096        public static final int TENTH_OF_TEVES = 22;
097        /** Tu Bishvat on the 15th day of Shevat, a minor holiday.*/
098        public static final int TU_BESHVAT = 23;
099        /** The fast of Esther, usually on the 13th day of Adar (or Adar II on leap years). It is earlier on some years.*/
100        public static final int FAST_OF_ESTHER = 24;
101        /** The holiday of Purim on the 14th day of Adar (or Adar II on leap years).*/
102        public static final int PURIM = 25;
103        /** The holiday of Shushan Purim on the 15th day of Adar (or Adar II on leap years).*/
104        public static final int SHUSHAN_PURIM = 26;
105        /** The holiday of Purim Katan on the 14th day of Adar I on a leap year when Purim is on Adar II, a minor holiday.*/
106        public static final int PURIM_KATAN = 27;
107        /**
108         * Rosh Chodesh, the new moon on the first day of the Jewish month, and the 30th day of the previous month in the
109         * case of a month with 30 days.
110         */
111        public static final int ROSH_CHODESH = 28;
112        /** Yom HaShoah, Holocaust Remembrance Day, usually held on the 27th of Nissan. If it falls on a Friday, it is moved
113         * to the 26th, and if it falls on a Sunday it is moved to the 28th. A {@link #isUseModernHolidays() modern holiday}.
114         */
115        public static final int YOM_HASHOAH = 29;
116        /**
117         * Yom HaZikaron, Israeli Memorial Day, held a day before Yom Ha'atzmaut.  A {@link #isUseModernHolidays() modern holiday}.
118         */
119        public static final int YOM_HAZIKARON = 30;
120        
121        /** Yom Ha'atzmaut, Israel Independence Day, the 5th of Iyar, but if it occurs on a Friday or Saturday, the holiday is
122         * moved back to Thursday, the 3rd of 4th of Iyar, and if it falls on a Monday, it is moved forward to Tuesday the
123         * 6th of Iyar.  A {@link #isUseModernHolidays() modern holiday}.*/
124        public static final int YOM_HAATZMAUT = 31;
125        /**
126         * Yom Yerushalayim or Jerusalem Day, on 28 Iyar. A {@link #isUseModernHolidays() modern holiday}.
127         */
128        public static final int YOM_YERUSHALAYIM = 32;
129        
130        /** The 33rd day of the Omer, the 18th of Iyar, a minor holiday.*/
131        public static final int LAG_BAOMER = 33;
132        
133        /** The holiday of Purim Katan on the 15th day of Adar I on a leap year when Purim is on Adar II, a minor holiday.*/
134        public static final int SHUSHAN_PURIM_KATAN = 34;
135        
136        /** The day following the last day of Pesach, Shavuos and Sukkos.*/
137        public static final int ISRU_CHAG = 35;
138        
139        /**
140         * The day before <em>Rosh Chodesh</em> (moved to Thursday if <em>Rosh Chodesh</em> is on a Friday or <em>Shabbos</em>) in most months.
141         * This constant is not actively in use.
142         * @see #isYomKippurKatan()
143         */
144        public static final int YOM_KIPPUR_KATAN = 36;
145        
146        /**
147         * The Monday, Thursday and Monday after the first <em>Shabbos</em> after <em>Rosh Chodesh Cheshvan</em> and <em>Iyar</em>) are BeHab
148         * days. This constant is not actively in use.
149         * @see #isBeHaB()
150         */
151        public static final int BEHAB = 37;
152
153        /**
154         * Is the calendar set to Israel, where some holidays have different rules.
155         * @see #getInIsrael()
156         * @see #setInIsrael(boolean)
157         */
158        private boolean inIsrael = false;
159        
160        /**
161         * Is the calendar set to have Purim <em>demukafim</em>, where Purim is celebrated on Shushan Purim.
162         * @see #getIsMukafChoma()
163         * @see #setIsMukafChoma(boolean)
164         */
165        private boolean isMukafChoma = false;
166
167        /**
168         * Is the calendar set to use modern Israeli holidays such as Yom Haatzmaut.
169         * @see #isUseModernHolidays()
170         * @see #setUseModernHolidays(boolean)
171         */
172        private boolean useModernHolidays = false;
173
174        /**
175         * List of <em>parshiyos</em> or special <em>Shabasos</em>. {@link #NONE} indicates a week without a <em>parsha</em>, while the enum for
176         * the <em>parsha</em> of {@link #VZOS_HABERACHA} exists for consistency, but is not currently used. The special <em>Shabasos</em> of
177         * Shekalim, Zachor, Para, Hachodesh, as well as Shabbos Shuva, Shira, Hagadol, Chazon and Nachamu are also represented in this collection
178         * of <em>parshiyos</em>.
179         * @see #getSpecialShabbos()
180         * @see #getParshah()
181         */
182        public enum Parsha {
183                /**NONE A week without any <em>parsha</em> such as <em>Shabbos Chol Hamoed</em> */NONE,
184                /**BERESHIS*/BERESHIS, /**NOACH*/NOACH, /**LECH_LECHA*/LECH_LECHA, /**VAYERA*/VAYERA, /**CHAYEI_SARA*/CHAYEI_SARA, /**TOLDOS*/TOLDOS, 
185                /**VAYETZEI*/VAYETZEI, /**VAYISHLACH*/VAYISHLACH, /**VAYESHEV*/VAYESHEV, /**MIKETZ*/MIKETZ, /**VAYIGASH*/VAYIGASH, /**VAYECHI*/VAYECHI,
186                /**SHEMOS*/SHEMOS, /**VAERA*/VAERA, /**BO*/BO, /**BESHALACH*/BESHALACH, /**YISRO*/YISRO, /**MISHPATIM*/MISHPATIM, /**TERUMAH*/TERUMAH,
187                /**TETZAVEH*/TETZAVEH, /***KI_SISA*/KI_SISA, /**VAYAKHEL*/VAYAKHEL, /**PEKUDEI*/PEKUDEI, /**VAYIKRA*/VAYIKRA, /**TZAV*/TZAV, /**SHMINI*/SHMINI, 
188                /**TAZRIA*/TAZRIA, /**METZORA*/METZORA, /**ACHREI_MOS*/ACHREI_MOS, /**KEDOSHIM*/KEDOSHIM, /**EMOR*/EMOR, /**BEHAR*/BEHAR, /**BECHUKOSAI*/BECHUKOSAI,
189                /**BAMIDBAR*/BAMIDBAR, /**NASSO*/NASSO, /**BEHAALOSCHA*/BEHAALOSCHA, /**SHLACH*/SHLACH, /**KORACH*/KORACH, /**CHUKAS*/CHUKAS, /**BALAK*/BALAK,
190                /**PINCHAS*/PINCHAS, /**MATOS*/MATOS, /**MASEI*/MASEI, /**DEVARIM*/DEVARIM, /**VAESCHANAN*/VAESCHANAN, /**EIKEV*/EIKEV, /**REEH*/REEH,
191                /**SHOFTIM*/SHOFTIM, /**KI_SEITZEI*/KI_SEITZEI, /**KI_SAVO*/KI_SAVO, /**NITZAVIM*/NITZAVIM, /**VAYEILECH*/VAYEILECH, /**HAAZINU*/HAAZINU,
192                /**VZOS_HABERACHA*/VZOS_HABERACHA, /**The double parsha of Vayakhel &amp; Peudei*/VAYAKHEL_PEKUDEI, /**The double <em>parsha</em> of Tazria
193                 * &amp; Metzora*/TAZRIA_METZORA,/**The double <em>parsha</em> of Achrei Mos &amp; Kedoshim*/ACHREI_MOS_KEDOSHIM,/**The double <em>parsha</em>
194                 * of Behar &amp; Bechukosai*/BEHAR_BECHUKOSAI,/**The double <em>parsha</em> of Chukas &amp; Balak*/CHUKAS_BALAK, /**The double
195                 * <em>parsha</em> of Matos &amp; Masei*/MATOS_MASEI,/**The double <em>parsha</em> of Nitzavim &amp; Vayelech*/NITZAVIM_VAYEILECH,
196                 /**The special <em>parsha</em> of Shekalim*/SHKALIM, /** The special <em>parsha</em> of Zachor*/ZACHOR, /**The special <em>parsha</em> of
197                  * Para*/PARA, /** The special <em>parsha</em> of Hachodesh*/HACHODESH, /**<em>Shabbos</em> Shuva*/SHUVA, /**<em>Shabbos</em> Shira*/SHIRA, 
198                  /**<em>Shabbos</em> Hagadol*/HAGADOL, /**<em>Shabbos</em> Chazon*/CHAZON, /**<em>Shabbos</em> Nachamu*/NACHAMU
199        };
200        
201        /**
202         * An array of <em>parshiyos</em> in the 17 possible combinations.
203         */
204        public static final Parsha[][] parshalist = {
205                {Parsha.NONE, Parsha.VAYEILECH, Parsha.HAAZINU, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL_PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.NONE, Parsha.SHMINI, Parsha.TAZRIA_METZORA, Parsha.ACHREI_MOS_KEDOSHIM, Parsha.EMOR, Parsha.BEHAR_BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
206                {Parsha.NONE, Parsha.VAYEILECH, Parsha.HAAZINU, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL_PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.NONE, Parsha.SHMINI, Parsha.TAZRIA_METZORA, Parsha.ACHREI_MOS_KEDOSHIM, Parsha.EMOR, Parsha.BEHAR_BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NONE, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS_BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
207                {Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL_PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.NONE, Parsha.NONE, Parsha.SHMINI, Parsha.TAZRIA_METZORA, Parsha.ACHREI_MOS_KEDOSHIM, Parsha.EMOR, Parsha.BEHAR_BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM},
208                {Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.NONE, Parsha.SHMINI, Parsha.TAZRIA_METZORA, Parsha.ACHREI_MOS_KEDOSHIM, Parsha.EMOR, Parsha.BEHAR_BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM},
209                {Parsha.NONE, Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL_PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.NONE, Parsha.SHMINI, Parsha.TAZRIA_METZORA, Parsha.ACHREI_MOS_KEDOSHIM, Parsha.EMOR, Parsha.BEHAR_BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM},
210                {Parsha.NONE, Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL_PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.NONE, Parsha.SHMINI, Parsha.TAZRIA_METZORA, Parsha.ACHREI_MOS_KEDOSHIM, Parsha.EMOR, Parsha.BEHAR_BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
211                {Parsha.NONE, Parsha.VAYEILECH, Parsha.HAAZINU, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.NONE, Parsha.ACHREI_MOS, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NONE, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS_BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
212                {Parsha.NONE, Parsha.VAYEILECH, Parsha.HAAZINU, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.NONE, Parsha.NONE, Parsha.ACHREI_MOS, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM},
213                {Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.ACHREI_MOS, Parsha.NONE, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS, Parsha.MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM},
214                {Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.ACHREI_MOS, Parsha.NONE, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS, Parsha.MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
215                {Parsha.NONE, Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.NONE, Parsha.ACHREI_MOS, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
216                {Parsha.NONE, Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.NONE, Parsha.ACHREI_MOS, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NONE, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS_BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
217                {Parsha.NONE, Parsha.VAYEILECH, Parsha.HAAZINU, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL_PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.NONE, Parsha.SHMINI, Parsha.TAZRIA_METZORA, Parsha.ACHREI_MOS_KEDOSHIM, Parsha.EMOR, Parsha.BEHAR_BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
218                {Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL_PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.NONE, Parsha.SHMINI, Parsha.TAZRIA_METZORA, Parsha.ACHREI_MOS_KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM},
219                {Parsha.NONE, Parsha.VAYEILECH, Parsha.HAAZINU, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.NONE, Parsha.ACHREI_MOS, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH},
220                {Parsha.NONE, Parsha.VAYEILECH, Parsha.HAAZINU, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.NONE, Parsha.ACHREI_MOS, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS, Parsha.MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM},
221                {Parsha.NONE, Parsha.NONE, Parsha.HAAZINU, Parsha.NONE, Parsha.NONE, Parsha.BERESHIS, Parsha.NOACH, Parsha.LECH_LECHA, Parsha.VAYERA, Parsha.CHAYEI_SARA, Parsha.TOLDOS, Parsha.VAYETZEI, Parsha.VAYISHLACH, Parsha.VAYESHEV, Parsha.MIKETZ, Parsha.VAYIGASH, Parsha.VAYECHI, Parsha.SHEMOS, Parsha.VAERA, Parsha.BO, Parsha.BESHALACH, Parsha.YISRO, Parsha.MISHPATIM, Parsha.TERUMAH, Parsha.TETZAVEH, Parsha.KI_SISA, Parsha.VAYAKHEL, Parsha.PEKUDEI, Parsha.VAYIKRA, Parsha.TZAV, Parsha.SHMINI, Parsha.TAZRIA, Parsha.METZORA, Parsha.NONE, Parsha.ACHREI_MOS, Parsha.KEDOSHIM, Parsha.EMOR, Parsha.BEHAR, Parsha.BECHUKOSAI, Parsha.BAMIDBAR, Parsha.NASSO, Parsha.BEHAALOSCHA, Parsha.SHLACH, Parsha.KORACH, Parsha.CHUKAS, Parsha.BALAK, Parsha.PINCHAS, Parsha.MATOS_MASEI, Parsha.DEVARIM, Parsha.VAESCHANAN, Parsha.EIKEV, Parsha.REEH, Parsha.SHOFTIM, Parsha.KI_SEITZEI, Parsha.KI_SAVO, Parsha.NITZAVIM_VAYEILECH}
222        };
223
224        /**
225         * Is this calendar set to return modern Israeli national holidays. By default, this value is false. The holidays
226         * are {@link #YOM_HASHOAH <em>Yom HaShoah</em>}, {@link #YOM_HAZIKARON <em>Yom Hazikaron</em>}, {@link
227         * #YOM_HAATZMAUT <em>Yom Ha'atzmaut</em>} and {@link #YOM_YERUSHALAYIM <em>Yom Yerushalayim</em>}.
228         * 
229         * @return the useModernHolidays true if set to return modern Israeli national holidays
230         * 
231         * @see #setUseModernHolidays(boolean)
232         */
233        public boolean isUseModernHolidays() {
234                return useModernHolidays;
235        }
236
237        /**
238         * Sets the calendar to return modern Israeli national holidays. By default, this value is false. The holidays are:
239         * {@link #YOM_HASHOAH <em>Yom HaShoah</em>}, {@link #YOM_HAZIKARON <em>Yom Hazikaron</em>}, {@link
240         * #YOM_HAATZMAUT <em>Yom Ha'atzmaut</em>} and {@link #YOM_YERUSHALAYIM <em>Yom Yerushalayim</em>}.
241         * 
242         * @param useModernHolidays
243         *            the useModernHolidays to set
244         * 
245         * @see #isUseModernHolidays()
246         */
247        public void setUseModernHolidays(boolean useModernHolidays) {
248                this.useModernHolidays = useModernHolidays;
249        }
250
251        /**
252         * Default constructor will set a default date to the current system date.
253         */
254        public JewishCalendar() {
255                super();
256        }
257
258        /**
259         * A constructor that initializes the date to the {@link java.util.Calendar Calendar} parameter.
260         * 
261         * @param zonedDateTime
262         *            the <code>ZonedDateTime</code> to set the calendar to
263         */
264        public JewishCalendar(ZonedDateTime zonedDateTime) {
265                super(zonedDateTime);
266        }
267
268        /**
269         * A constructor that initializes the date to the {@link java.time.LocalDate LocalDate} parameter.
270         * 
271         * @param localDate
272         *            the <code>LocalDate</code> to set the calendar to
273         */
274        public JewishCalendar(LocalDate localDate) {
275                super(localDate);
276        }
277
278        /**
279         * Creates a Jewish date based on a Jewish year, month and day of month.
280         * 
281         * @param jewishYear
282         *            the Jewish year
283         * @param jewishMonth
284         *            the Jewish month. The method expects a 1 for Nissan ... 12 for Adar and 13 for Adar II. Use the
285         *            constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar II) to avoid any
286         *            confusion.
287         * @param jewishDayOfMonth
288         *            the Jewish day of month. If 30 is passed in for a month with only 29 days (for example {@link #IYAR},
289         *            or {@link #KISLEV} in a year that {@link #isKislevShort()}), the 29th (last valid date of the month)
290         *            will be set
291         * @throws IllegalArgumentException
292         *             if the day of month is &lt; 1 or &gt; 30, or a year of &lt; 0 is passed in.
293         */
294        public JewishCalendar(int jewishYear, int jewishMonth, int jewishDayOfMonth) {
295                super(jewishYear, jewishMonth, jewishDayOfMonth);
296        }
297
298        /**
299         * Creates a Jewish date based on a Jewish date and whether in Israel
300         * 
301         * @param jewishYear
302         *            the Jewish year
303         * @param jewishMonth
304         *            the Jewish month. The method expects a 1 for <em>Nissan</em> ... 12 for <em>Adar</em> and 13 for
305         *            <em>Adar II</em>. Use the constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a
306         *            leap year Adar II) to avoid any confusion.
307         * @param jewishDayOfMonth
308         *            the Jewish day of month. If 30 is passed in for a month with only 29 days (for example {@link #IYAR},
309         *            or {@link #KISLEV} in a year that {@link #isKislevShort()}), the 29th (last valid date of the month)
310         *            will be set.
311         * @param inIsrael
312         *            whether in Israel. This affects <em>Yom Tov</em> calculations
313         */
314        public JewishCalendar(int jewishYear, int jewishMonth, int jewishDayOfMonth, boolean inIsrael) {
315                super(jewishYear, jewishMonth, jewishDayOfMonth);
316                setInIsrael(inIsrael);
317        }
318
319        /**
320         * Sets whether to use Israel holiday scheme or not. Default is false.
321         * 
322         * @param inIsrael
323         *            set to true for calculations for Israel
324         * 
325         * @see #getInIsrael()
326         */
327        public void setInIsrael(boolean inIsrael) {
328                this.inIsrael = inIsrael;
329        }
330
331        /**
332         * Gets whether Israel holiday scheme is used or not. The default (if not set) is false.
333         * 
334         * @return if the calendar is set to Israel
335         * 
336         * @see #setInIsrael(boolean)
337         */
338        public boolean getInIsrael() {
339                return inIsrael;
340        }
341        
342        /**
343         * Returns if the city is set as a city surrounded by a wall from the time of Yehoshua, and Shushan Purim
344         * should be celebrated as opposed to regular Purim.
345         * @return if the city is set as a city surrounded by a wall from the time of Yehoshua, and Shushan Purim
346         *         should be celebrated as opposed to regular Purim.
347         * @see #setIsMukafChoma(boolean)
348         */
349        public boolean getIsMukafChoma() {
350                return isMukafChoma;
351        }
352
353        /**
354         * Sets if the location is surrounded by a wall from the time of Yehoshua, and Shushan Purim should be
355         * celebrated as opposed to regular Purim. This should be set for Yerushalayim, Shushan and other cities.
356         * @param isMukafChoma is the city surrounded by a wall from the time of Yehoshua.
357         * 
358         * @see #getIsMukafChoma()
359         */
360        public void setIsMukafChoma(boolean isMukafChoma) {
361                this.isMukafChoma = isMukafChoma;
362        }
363        
364        /**
365         * <a href="https://en.wikipedia.org/wiki/Birkat_Hachama">Birkas Hachamah</a> is recited every 28 years based on
366         * <em>Tekufas Shmuel</em> (Julian years) that a year is 365.25 days. The <a href="https://en.wikipedia.org/wiki/Maimonides"
367         * >Rambam</a> in <a href="http://hebrewbooks.org/pdfpager.aspx?req=14278&amp;st=&amp;pgnum=323">Hilchos Kiddush Hachodesh 9:3</a>
368         * states that <em>tekufas Nissan</em> of year 1 was 7 days + 9 hours before <em>molad Nissan</em>. This is calculated as every
369         * 10,227 days (28 * 365.25).  
370         * @return true for a day that <em>Birkas Hachamah</em> is recited.
371         */
372        public boolean isBirkasHachamah() {
373                int elapsedDays = getJewishCalendarElapsedDays(getJewishYear()); //elapsed days since molad ToHu
374                elapsedDays = elapsedDays + getDaysSinceStartOfJewishYear(); //elapsed days to the current calendar date
375                
376                /* Molad Nissan year 1 was 177 days after molad tohu of Tishrei. We multiply 29.5 days * 6 months from Tishrei
377                 * to Nissan = 177. Subtract 7 days since tekufas Nissan was 7 days and 9 hours before the molad as stated in the Rambam
378                 * and we are now at 170 days. Because getJewishCalendarElapsedDays and getDaysSinceStartOfJewishYear use the value for
379                 * Rosh Hashana as 1, we have to add 1 day for a total of 171. To this add a day since the tekufah is on a Tuesday
380                 * night, and we push off the bracha to Wednesday morning resulting in the 172 used in the calculation.
381                 */
382                // Pure integer math prevents implicit promotion to double. 28 * 365.25 is exactly 10227 days.
383                // Using "return elapsedDays % (28 * 365.25) == 172" would break with an integer overflow in Jewish year >= 5,879,101 😀
384                return elapsedDays % 10227 == 172; // 28 years of 365.25 days + the offset from molad tohu mentioned above
385        }
386
387        /**
388         * Return the type of year for <em>parsha</em> calculations. The algorithm follows the
389         * <a href="http://hebrewbooks.org/pdfpager.aspx?req=14268&amp;st=&amp;pgnum=222">Luach Arba'ah Shearim</a> in the Tur Ohr Hachaim.
390         * @return the type of year for <em>parsha</em> calculations.
391         */
392        private int getParshaYearType() {
393                int roshHashanaDayOfWeek = (getJewishCalendarElapsedDays(getJewishYear()) + 1) % 7; // plus one to the original Rosh Hashana of year 1 to get a week starting on Sunday
394                if (roshHashanaDayOfWeek == 0) {
395                        roshHashanaDayOfWeek = 7; // convert 0 to 7 for Shabbos for readability
396                }
397                if (isJewishLeapYear()) {
398                        switch (roshHashanaDayOfWeek) {
399                        case Calendar.MONDAY:
400                                if (isKislevShort()) { //BaCh
401                                        if (getInIsrael()) {
402                                                return 14;
403                                        }
404                                        return 6;
405                                }
406                                if (isCheshvanLong()) { //BaSh
407                                        if (getInIsrael()) {
408                                                return 15;
409                                        }
410                                        return 7;
411                                }
412                                break;
413                        case Calendar.TUESDAY: //Gak
414                                if (getInIsrael()) {
415                                        return 15;
416                                }
417                                return 7;
418                        case Calendar.THURSDAY:
419                                if (isKislevShort()) { //HaCh
420                                        return 8;
421                                }
422                                if (isCheshvanLong()) { //HaSh
423                                        return 9;
424                                }
425                                break;
426                        case Calendar.SATURDAY:
427                                if (isKislevShort()) { //ZaCh
428                                        return 10;
429                                }
430                                if (isCheshvanLong()) { //ZaSh
431                                        if (getInIsrael()) {
432                                                return 16;
433                                        }
434                                        return 11;
435                                }
436                                break;
437                        }
438                } else { //not a leap year
439                        switch (roshHashanaDayOfWeek) {
440                        case Calendar.MONDAY:
441                                if (isKislevShort()) { //BaCh
442                                        return 0;
443                                }
444                                if (isCheshvanLong()) { //BaSh
445                                        if (getInIsrael()) {
446                                                return 12;
447                                        }
448                                        return 1;
449                                }
450                                break;
451                        case Calendar.TUESDAY: //GaK
452                                if (getInIsrael()) {
453                                        return 12;
454                                }
455                                return 1;
456                        case Calendar.THURSDAY:
457                                if (isCheshvanLong()) { //HaSh
458                                        return 3;
459                                }
460                                if (!isKislevShort()) { //Hak
461                                        if (getInIsrael()) {
462                                                return 13;
463                                        }
464                                        return 2;
465                                }
466                                break;
467                        case Calendar.SATURDAY:
468                                if (isKislevShort()) { //ZaCh
469                                        return 4;
470                                }
471                                if (isCheshvanLong()) { //ZaSh
472                                        return 5;
473                                }
474                                break;
475                        }
476                }
477                return -1; //keep the compiler happy
478        }
479
480        /**
481         * Returns this week's {@link Parsha <em>Parsha</em>} if it is <em>Shabbos</em>. It returns {@link Parsha#NONE} if the date
482         * is a weekday or if there is no <em>parsha</em> that week (for example <em>Yom Tov</em> that falls on a <em>Shabbos</em>).
483         * 
484         * @return the current <em>parsha</em>.
485         */
486        public synchronized Parsha getParshah() {
487                if (getDayOfWeek() != Calendar.SATURDAY) {
488                        return Parsha.NONE;
489                }
490                
491                int yearType = getParshaYearType();
492                int roshHashanaDayOfWeek = getJewishCalendarElapsedDays(getJewishYear()) % 7;
493                int day = roshHashanaDayOfWeek + getDaysSinceStartOfJewishYear();
494                
495                if (yearType >= 0) { // negative year should be impossible, but let's cover all bases
496                        return parshalist[yearType][day/7];
497                }
498                return Parsha.NONE; //keep the compiler happy
499        }
500        
501        /**
502         * Returns the upcoming {@link Parsha <em>Parsha</em>} regardless of if it is the weekday or <em>Shabbos</em> (where next
503         * Shabbos's <em>Parsha</em> will be returned. This is unlike {@link #getParshah()} that returns {@link Parsha#NONE} if
504         * the date is not <em>Shabbos</em>. If the upcoming <em>Shabbos</em> is a <em>Yom Tov</em> and has no <em>Parsha</em>, the
505         * following week's <em>Parsha</em> will be returned.
506         * 
507         * @return the upcoming <em>parsha</em>.
508         */
509        public Parsha getUpcomingParshah() {
510                JewishCalendar clone = (JewishCalendar) clone();
511                int daysToShabbos = (Calendar.SATURDAY - getDayOfWeek()  + 7) % 7;
512                if (getDayOfWeek() != Calendar.SATURDAY) {
513            clone.plusDays(daysToShabbos);
514                } else {
515                        clone.plusDays( 7);
516                }
517                while(clone.getParshah() == Parsha.NONE) { //Yom Kippur / Sukkos or Pesach with 2 potential non-parsha Shabbosim in a row
518                        clone.plusDays(7);
519                }
520                return clone.getParshah();
521        }
522        
523        /**
524         * Returns a {@link Parsha <em>Parsha</em>} enum if the <em>Shabbos</em> is one of the four <em>parshiyos</em> of {@link
525         * Parsha#SHKALIM <em>Shkalim</em>}, {@link Parsha#ZACHOR <em>Zachor</em>}, {@link Parsha#PARA <em>Para</em>}, {@link
526         * Parsha#HACHODESH <em>Hachodesh</em>}, or five other special <em>Shabbasos</em> of {@link Parsha#HAGADOL <em>Hagadol</em>},
527         * {@link Parsha#CHAZON <em>Chazon</em>}, {@link Parsha#NACHAMU <em>Nachamu</em>}, {@link Parsha#SHUVA <em>Shuva</em>},
528         * {@link Parsha#SHIRA <em>Shira</em>}, or {@link Parsha#NONE Parsha.NONE} for a regular <em>Shabbos</em> (or any weekday).
529         * 
530         * @return one of the four <em>parshiyos</em> of {@link Parsha#SHKALIM <em>Shkalim</em>}, {@link Parsha#ZACHOR <em>Zachor</em>},
531         *              {@link Parsha#PARA <em>Para</em>}, {@link Parsha#HACHODESH <em>Hachodesh</em>}, or five other special <em>Shabbasos</em>
532         *              of {@link Parsha#HAGADOL <em>Hagadol</em>}, {@link Parsha#CHAZON <em>Chazon</em>}, {@link Parsha#NACHAMU <em>Nachamu</em>},
533         *              {@link Parsha#SHUVA <em>Shuva</em>}, {@link Parsha#SHIRA <em>Shira</em>}, or {@link Parsha#NONE Parsha.NONE} for a regular
534         *              <em>Shabbos</em> (or any weekday).
535         */
536        public synchronized Parsha getSpecialShabbos() {
537                if (getDayOfWeek() == Calendar.SATURDAY) {
538                        if ((getJewishMonth() == SHEVAT && !isJewishLeapYear()) || (getJewishMonth() == ADAR && isJewishLeapYear())) {
539                                if (getJewishDayOfMonth() == 25 || getJewishDayOfMonth() == 27 || getJewishDayOfMonth() == 29) {
540                                        return Parsha.SHKALIM;
541                                }
542                        }
543                        if ((getJewishMonth() == ADAR && !isJewishLeapYear()) || getJewishMonth() == ADAR_II) {
544                                if (getJewishDayOfMonth() == 1) {
545                                        return Parsha.SHKALIM;
546                                }
547                                if (getJewishDayOfMonth() == 8 || getJewishDayOfMonth() == 9 || getJewishDayOfMonth() == 11 || getJewishDayOfMonth() == 13) {
548                                        return Parsha.ZACHOR;
549                                }
550                                if (getJewishDayOfMonth() == 18 || getJewishDayOfMonth() == 20 || getJewishDayOfMonth() == 22 || getJewishDayOfMonth() == 23) {
551                                        return Parsha.PARA;
552                                }
553                                if (getJewishDayOfMonth() == 25 || getJewishDayOfMonth() == 27 || getJewishDayOfMonth() == 29) {
554                                        return Parsha.HACHODESH;
555                                }
556                        }
557                        if (getJewishMonth() == NISSAN) {
558                                if (getJewishDayOfMonth() == 1) {
559                                        return Parsha.HACHODESH;
560                                }
561                                if (getJewishDayOfMonth() >= 8 && getJewishDayOfMonth() <= 14) {
562                                        return Parsha.HAGADOL;
563                                }
564                        }
565                        if (getJewishMonth() == AV) {
566                                if (getJewishDayOfMonth() >= 4 && getJewishDayOfMonth() <= 9) {
567                                        return Parsha.CHAZON;
568                                }
569                                if (getJewishDayOfMonth() >= 10 && getJewishDayOfMonth() <= 16) {
570                                        return Parsha.NACHAMU;
571                                }
572                        }
573                        if (getJewishMonth() == TISHREI) {
574                                if (getJewishDayOfMonth() >= 3 && getJewishDayOfMonth() <= 8) {
575                                        return Parsha.SHUVA;
576                                }
577                                
578                        }
579                        if (getParshah() == Parsha.BESHALACH) {
580                                return Parsha.SHIRA;
581                        }
582                }
583                return Parsha.NONE;
584        }
585
586        /**
587         * Returns an index of the Jewish holiday or fast day for the current day, or a -1 if there is no holiday for this day.
588         * There are constants in this class representing each <em>Yom Tov</em>. Formatting of the <em>Yomim tovim</em> is done
589         * in the {@link HebrewDateFormatter#formatYomTov(JewishCalendar)}.
590         * 
591         * @todo Consider using enums instead of the constant ints.
592         * 
593         * @return the index of the holiday such as the constant {@link #LAG_BAOMER} or {@link #YOM_KIPPUR} or a -1 if it is not a holiday.
594         * 
595         * @see HebrewDateFormatter#formatYomTov(JewishCalendar)
596         */
597        public synchronized int getYomTovIndex() {
598                final int day = getJewishDayOfMonth();
599                final int dayOfWeek = getDayOfWeek();
600
601                // check by month (starting from Nissan)
602                switch (getJewishMonth()) {
603                case NISSAN:
604                        if (day == 14) {
605                                return EREV_PESACH;
606                        }
607                        if (day == 15 || day == 21
608                                        || (!inIsrael && (day == 16 || day == 22))) {
609                                return PESACH;
610                        }
611                        if (day >= 17 && day <= 20 || day == 16) {
612                                return CHOL_HAMOED_PESACH;
613                        }
614                        if ((day == 22 && inIsrael) || (day == 23 && !inIsrael)) {
615                                return ISRU_CHAG;
616                        }
617                        if (isUseModernHolidays()
618                                        && ((day == 26 && dayOfWeek == Calendar.THURSDAY)
619                                                        || (day == 28 && dayOfWeek == Calendar.MONDAY)
620                                                        || (day == 27 && dayOfWeek != Calendar.SUNDAY && dayOfWeek != Calendar.FRIDAY))) {
621                                return YOM_HASHOAH;
622                        }
623                        break;
624                case IYAR:
625                        if (isUseModernHolidays()
626                                        && ((day == 4 && dayOfWeek == Calendar.TUESDAY)
627                                                        || ((day == 3 || day == 2) && dayOfWeek == Calendar.WEDNESDAY) || (day == 5 && dayOfWeek == Calendar.MONDAY))) {
628                                return YOM_HAZIKARON;
629                        }
630                        // if 5 Iyar falls on Wed, Yom Haatzmaut is that day. If it falls on Friday or Shabbos, it is moved back to
631                        // Thursday. If it falls on Monday it is moved to Tuesday
632                        if (isUseModernHolidays()
633                                        && ((day == 5 && dayOfWeek == Calendar.WEDNESDAY)
634                                                        || ((day == 4 || day == 3) && dayOfWeek == Calendar.THURSDAY) || (day == 6 && dayOfWeek == Calendar.TUESDAY))) {
635                                return YOM_HAATZMAUT;
636                        }
637                        if (day == 14) {
638                                return PESACH_SHENI;
639                        }
640                        if (day == 18) {
641                                return LAG_BAOMER;
642                        }
643                        if (isUseModernHolidays() && day == 28) {
644                                return YOM_YERUSHALAYIM;
645                        }
646                        break;
647                case SIVAN:
648                        if (day == 5) {
649                                return EREV_SHAVUOS;
650                        }
651                        if (day == 6 || (day == 7 && !inIsrael)) { 
652                                return SHAVUOS; 
653                    }
654                    if ((day == 7 && inIsrael) || (day == 8 && !inIsrael)) { 
655                        return ISRU_CHAG; 
656                    }
657                        break;
658                case TAMMUZ:
659                        // push off the fast day if it falls on Shabbos
660                        if ((day == 17 && dayOfWeek != Calendar.SATURDAY)
661                                        || (day == 18 && dayOfWeek == Calendar.SUNDAY)) {
662                                return SEVENTEEN_OF_TAMMUZ;
663                        }
664                        break;
665                case AV:
666                        // if Tisha B'av falls on Shabbos, push off until Sunday
667                        if ((dayOfWeek == Calendar.SUNDAY && day == 10)
668                                        || (dayOfWeek != Calendar.SATURDAY && day == 9)) {
669                                return TISHA_BEAV;
670                        }
671                        if (day == 15) {
672                                return TU_BEAV;
673                        }
674                        break;
675                case ELUL:
676                        if (day == 29) {
677                                return EREV_ROSH_HASHANA;
678                        }
679                        break;
680                case TISHREI:
681                        if (day == 1 || day == 2) {
682                                return ROSH_HASHANA;
683                        }
684                        if ((day == 3 && dayOfWeek != Calendar.SATURDAY) || (day == 4 && dayOfWeek == Calendar.SUNDAY)) {
685                                // push off Tzom Gedalia if it falls on Shabbos
686                                return FAST_OF_GEDALYAH;
687                        }
688                        if (day == 9) {
689                                return EREV_YOM_KIPPUR;
690                        }
691                        if (day == 10) {
692                                return YOM_KIPPUR;
693                        }
694                        if (day == 14) {
695                                return EREV_SUCCOS;
696                        }
697                        if (day == 15 || (day == 16 && !inIsrael)) {
698                                return SUCCOS;
699                        }
700                        if (day >= 16 && day <= 20) {
701                                return CHOL_HAMOED_SUCCOS;
702                        }
703                        if (day == 21) {
704                                return HOSHANA_RABBA;
705                        }
706                        if (day == 22) {
707                                return SHEMINI_ATZERES;
708                        }
709                        if (day == 23 && !inIsrael) {
710                                return SIMCHAS_TORAH;
711                        }
712                        if ((day == 23 && inIsrael) || (day == 24 && !inIsrael)) {
713                                return ISRU_CHAG;
714                        }
715                        break;
716                case KISLEV: // no yomtov in CHESHVAN
717                        if (day >= 25) {
718                                return CHANUKAH;
719                        }
720                        break;
721                case TEVES:
722                        if (day == 1 || day == 2
723                                        || (day == 3 && isKislevShort())) {
724                                return CHANUKAH;
725                        }
726                        if (day == 10) {
727                                return TENTH_OF_TEVES;
728                        }
729                        break;
730                case SHEVAT:
731                        if (day == 15) {
732                                return TU_BESHVAT;
733                        }
734                        break;
735                case ADAR:
736                        if (!isJewishLeapYear()) {
737                                // if 13th Adar falls on Friday or Shabbos, push back to Thursday
738                                if (((day == 11 || day == 12) && dayOfWeek == Calendar.THURSDAY)
739                                                || (day == 13 && !(dayOfWeek == Calendar.FRIDAY || dayOfWeek == Calendar.SATURDAY))) {
740                                        return FAST_OF_ESTHER;
741                                }
742                                if (day == 14) {
743                                        return PURIM;
744                                }
745                                if (day == 15) {
746                                        return SHUSHAN_PURIM;
747                                }
748                        } else { // else if a leap year
749                                if (day == 14) {
750                                        return PURIM_KATAN;
751                                }
752                                if (day == 15) {
753                                        return SHUSHAN_PURIM_KATAN;
754                                }
755                        }
756                        break;
757                case ADAR_II:
758                        // if 13th Adar falls on Friday or Shabbos, push back to Thursday
759                        if (((day == 11 || day == 12) && dayOfWeek == Calendar.THURSDAY)
760                                        || (day == 13 && !(dayOfWeek == Calendar.FRIDAY || dayOfWeek == Calendar.SATURDAY))) {
761                                return FAST_OF_ESTHER;
762                        }
763                        if (day == 14) {
764                                return PURIM;
765                        }
766                        if (day == 15) {
767                                return SHUSHAN_PURIM;
768                        }
769                        break;
770                }
771                // if we get to this stage, then there are no holidays for the given date return -1
772                return -1;
773        }
774
775        /**
776         * Returns true if the current day is <em>Yom Tov</em>. The method returns true even for holidays such as {@link #CHANUKAH}
777         * and minor ones such as {@link #TU_BEAV} and {@link #PESACH_SHENI}. <em>Erev Yom Tov</em> (with the exception of
778         * {@link #HOSHANA_RABBA} and <em>erev</em> the second days of {@link #PESACH}) returns false, as do {@link #isTaanis() fast
779         * days} besides {@link #YOM_KIPPUR}. Use {@link #isAssurBemelacha()} to find the days that have a prohibition of work. 
780         * 
781         * @return true if the current day is a Yom Tov
782         * 
783         * @see #getYomTovIndex()
784         * @see #isErevYomTov()
785         * @see #isErevYomTovSheni()
786         * @see #isTaanis()
787         * @see #isAssurBemelacha()
788         * @see #isCholHamoed()
789         */
790        public boolean isYomTov() {
791                int holidayIndex = getYomTovIndex();
792                if ((isErevYomTov() && ! ( holidayIndex == HOSHANA_RABBA || holidayIndex == CHOL_HAMOED_PESACH))
793                                || (isTaanis() && holidayIndex != YOM_KIPPUR) || holidayIndex == ISRU_CHAG) {
794                        return false;
795                }
796                return getYomTovIndex() != -1;
797        }
798
799        /**
800         * Returns true if the <em>Yom Tov</em> day has a <em>melacha</em> (work)  prohibition. This method will return false for a
801         * non-<em>Yom Tov</em> day, even if it is <em>Shabbos</em>.
802         *
803         * @return if the <em>Yom Tov</em> day has a <em>melacha</em> (work)  prohibition.
804         */
805        public boolean isYomTovAssurBemelacha() {
806                int holidayIndex = getYomTovIndex();
807                return holidayIndex == PESACH || holidayIndex == SHAVUOS || holidayIndex == SUCCOS || holidayIndex == SHEMINI_ATZERES ||
808                                holidayIndex == SIMCHAS_TORAH || holidayIndex == ROSH_HASHANA  || holidayIndex == YOM_KIPPUR;
809        }
810        
811        /**
812         * Returns true if it is <em>Shabbos</em> or if it is a <em>Yom Tov</em> day that has a <em>melacha</em> (work)  prohibition.
813         * 
814         * @return if the day is a <em>Yom Tov</em> that is <em>assur bemlacha</em> or <em>Shabbos</em>
815         */
816        public boolean isAssurBemelacha() {
817                return getDayOfWeek() == Calendar.SATURDAY || isYomTovAssurBemelacha();
818        }
819        
820        /**
821         * Returns if <em>melacha</em> is permissible at night at the end of a day that was {@link #isAssurBemelacha()} (i.e. that the
822         * following day is not <em>assur bemelacha</em>). If it is a case of a <em>Yom Tov</em> night that falls on a <em>motzai
823         * Shabbos</em> that has <em>havdalah</em> in <em>kiddush</em>, false will be returned. Don't rely on this to determine if
824         * <em>havdalah</em> should be recited.
825         *
826         * @return {@code true} if <em>melacha</em> is permissible at night at the end of a day that was {@link #isAssurBemelacha()}.
827         * @see #isAssurBemelacha()
828         */
829        public boolean isTonightMutarBemelacha() {
830                if (!isAssurBemelacha()) {
831                        return false;
832                }
833                JewishCalendar tomorrow = (JewishCalendar) clone();
834                tomorrow.plusDays(1);
835                return !tomorrow.isAssurBemelacha();
836        }
837        
838        /**
839         * Returns true if the day has candle lighting. This will return true on <em>Erev Shabbos</em>, <em>Erev Yom Tov</em>, the
840         * first day of <em>Rosh Hashana</em> and the first days of <em>Yom Tov</em> out of Israel. It is identical
841         * to calling {@link #isTomorrowShabbosOrYomTov()}.
842         * 
843         * @return if the day has candle lighting.
844         * 
845         * @see #isTomorrowShabbosOrYomTov()
846         */
847        public boolean hasCandleLighting() {
848                return isTomorrowShabbosOrYomTov();
849        }
850        
851        /**
852         * Returns true if tomorrow is <em>Shabbos</em> or <em>Yom Tov</em>. This will return true on <em>Erev Shabbos</em>,
853         * <em>Erev Yom Tov</em>, the first day of <em>Rosh Hashana</em> and <em>erev</em> the first days of <em>Yom Tov</em>
854         * out of Israel. It is identical to calling {@link #hasCandleLighting()}.
855         * 
856         * @return will return if the next day is <em>Shabbos</em> or <em>Yom Tov</em>.
857         * 
858         * @see #hasCandleLighting()
859         */
860        public boolean isTomorrowShabbosOrYomTov() {
861                return getDayOfWeek() == Calendar.FRIDAY || isErevYomTov() || isErevYomTovSheni();
862        }
863        
864        /**
865         * Returns true if the day is the second day of <em>Yom Tov</em>. This impacts the second day of <em>Rosh Hashana</em> everywhere and
866         * the second days of Yom Tov in <em>chutz laaretz</em> (out of Israel).
867         * 
868         * @return  if the day is the second day of <em>Yom Tov</em>.
869         */
870        public boolean isErevYomTovSheni() {
871                return (getJewishMonth() == TISHREI && (getJewishDayOfMonth() == 1))
872                || (! getInIsrael()
873                                && ((getJewishMonth() == NISSAN && (getJewishDayOfMonth() == 15 || getJewishDayOfMonth() == 21))
874                                || (getJewishMonth() == TISHREI && (getJewishDayOfMonth() == 15 || getJewishDayOfMonth() == 22))
875                                || (getJewishMonth() == SIVAN && getJewishDayOfMonth() == 6 )));
876        }
877
878        /**
879         * Returns true if the current day is <em>Aseres Yemei Teshuva</em>.
880         * 
881         * @return if the current day is <em>Aseres Yemei Teshuva</em>
882         */
883        public boolean isAseresYemeiTeshuva() {
884                return getJewishMonth() == TISHREI && getJewishDayOfMonth() <= 10;
885        }
886        
887        /**
888         * Returns true if the current day is <em>Pesach</em> (either  the <em>Yom Tov</em> of <em>Pesach</em> or<em>Chol Hamoed Pesach</em>).
889         * 
890         * @return true if the current day is <em>Pesach</em> (either  the <em>Yom Tov</em> of <em>Pesach</em> or<em>Chol Hamoed Pesach</em>).
891         * @see #isYomTov()
892         * @see #isCholHamoedPesach()
893         * @see #PESACH
894         * @see #CHOL_HAMOED_PESACH
895         */
896        public boolean isPesach() {
897                int holidayIndex = getYomTovIndex();
898                return holidayIndex == PESACH || holidayIndex == CHOL_HAMOED_PESACH;
899        }
900        
901        /**
902         * Returns true if the current day is <em>Chol Hamoed</em> of <em>Pesach</em>.
903         *
904         * @return true if the current day is <em>Chol Hamoed</em> of <em>Pesach</em>
905         * @see #isYomTov()
906         * @see #isPesach()
907         * @see #CHOL_HAMOED_PESACH
908         */
909        public boolean isCholHamoedPesach() {
910                int holidayIndex = getYomTovIndex();
911                return holidayIndex == CHOL_HAMOED_PESACH;
912        }
913        
914        /**
915         * Returns true if the current day is <em>Shavuos</em>.
916         *
917         * @return true if the current day is <em>Shavuos</em>.
918         * @see #isYomTov()
919         * @see #SHAVUOS
920         */
921        public boolean isShavuos() {
922                int holidayIndex = getYomTovIndex();
923                return holidayIndex == SHAVUOS;
924        }
925        
926        /**
927         * Returns true if the current day is <em>Rosh Hashana</em>.
928         *
929         * @return true if the current day is <em>Rosh Hashana</em>.
930         * @see #isYomTov()
931         * @see #ROSH_HASHANA
932         */
933        public boolean isRoshHashana() {
934                int holidayIndex = getYomTovIndex();
935                return holidayIndex == ROSH_HASHANA;
936        }
937        
938        /**
939         * Returns true if the current day is <em>Yom Kippur</em>.
940         *
941         * @return true if the current day is <em>Yom Kippur</em>.
942         * @see #isYomTov()
943         * @see #YOM_KIPPUR
944         */
945        public boolean isYomKippur() {
946                int holidayIndex = getYomTovIndex();
947                return holidayIndex == YOM_KIPPUR;
948        }
949        
950        /**
951         * Returns true if the current day is <em>Succos</em> (either  the <em>Yom Tov</em> of <em>Succos</em> or<em>Chol Hamoed Succos</em>).
952         * It will return false for {@link #isShminiAtzeres() Shmini Atzeres} and {@link #isSimchasTorah() Simchas Torah}.
953         * 
954         * @return true if the current day is <em>Succos</em> (either  the <em>Yom Tov</em> of <em>Succos</em> or<em>Chol Hamoed Succos</em>.
955         * @see #isYomTov()
956         * @see #isCholHamoedSuccos()
957         * @see #isHoshanaRabba()
958         * @see #SUCCOS
959         * @see #CHOL_HAMOED_SUCCOS
960         * @see #HOSHANA_RABBA
961         */
962        public boolean isSuccos() {
963                int holidayIndex = getYomTovIndex();
964                return holidayIndex == SUCCOS || holidayIndex == CHOL_HAMOED_SUCCOS || holidayIndex == HOSHANA_RABBA;
965        }
966        
967        /**
968         * Returns true if the current day is <em>Hoshana Rabba</em>.
969         *
970         * @return true if the current day is <em>Hoshana Rabba</em>.
971         * @see #isYomTov()
972         * @see #HOSHANA_RABBA
973         */
974        public boolean isHoshanaRabba() {
975                int holidayIndex = getYomTovIndex();
976                return holidayIndex == HOSHANA_RABBA;
977        }
978        
979        /**
980         * Returns true if the current day is <em>Shmini Atzeres</em>.
981         *
982         * @return true if the current day is <em>Shmini Atzeres</em>.
983         * @see #isYomTov()
984         * @see #SHEMINI_ATZERES
985         */
986        public boolean isShminiAtzeres() {
987                int holidayIndex = getYomTovIndex();
988                return holidayIndex == SHEMINI_ATZERES;
989        }
990        
991        /**
992         * Returns true if the current day is <em>Simchas Torah</em>. This will always return false if {@link #getInIsrael() in Israel}
993         *
994         * @return true if the current day is <em>Shmini Atzeres</em>.
995         * @see #isYomTov()
996         * @see #SIMCHAS_TORAH
997         */
998        public boolean isSimchasTorah() {
999                int holidayIndex = getYomTovIndex();
1000                //if in Israel, Holiday index of SIMCHAS_TORAH will not be returned by getYomTovIndex()
1001                return holidayIndex == SIMCHAS_TORAH;
1002        }
1003        
1004        /**
1005         * Returns true if the current day is <em>Chol Hamoed</em> of <em>Succos</em>.
1006         *
1007         * @return true if the current day is <em>Chol Hamoed</em> of <em>Succos</em>
1008         * @see #isYomTov()
1009         * @see #CHOL_HAMOED_SUCCOS
1010         */
1011        public boolean isCholHamoedSuccos() {
1012                int holidayIndex = getYomTovIndex();
1013                return holidayIndex == CHOL_HAMOED_SUCCOS || holidayIndex == HOSHANA_RABBA;
1014        }
1015        
1016        /**
1017         * Returns true if the current day is <em>Chol Hamoed</em> of <em>Pesach</em> or <em>Succos</em>.
1018         * 
1019         * @return true if the current day is <em>Chol Hamoed</em> of <em>Pesach</em> or <em>Succos</em>
1020         * @see #isYomTov()
1021         * @see #CHOL_HAMOED_PESACH
1022         * @see #CHOL_HAMOED_SUCCOS
1023         */
1024        public boolean isCholHamoed() {
1025                return isCholHamoedPesach() || isCholHamoedSuccos();
1026        }
1027
1028        /**
1029         * Returns true if the current day is <em>Erev Yom Tov</em>. The method returns true for <em>Erev</em> - <em>Pesach</em>
1030         * (first and last days), <em>Shavuos</em>, <em>Rosh Hashana</em>, <em>Yom Kippur</em>, <em>Succos</em> and <em>Hoshana
1031         * Rabba</em>.
1032         * 
1033         * @return true if the current day is <em>Erev</em> - <em>Pesach</em>, <em>Shavuos</em>, <em>Rosh Hashana</em>, <em>Yom
1034         * Kippur</em>, <em>Succos</em> and <em>Hoshana Rabba</em>.
1035         * @see #isYomTov()
1036         * @see #isErevYomTovSheni()
1037         */
1038        public boolean isErevYomTov() {
1039                int holidayIndex = getYomTovIndex();
1040                return holidayIndex == EREV_PESACH || holidayIndex == EREV_SHAVUOS || holidayIndex == EREV_ROSH_HASHANA
1041                                || holidayIndex == EREV_YOM_KIPPUR || holidayIndex == EREV_SUCCOS || holidayIndex == HOSHANA_RABBA
1042                                || (holidayIndex == CHOL_HAMOED_PESACH && getJewishDayOfMonth() == 20);
1043        }
1044
1045        /**
1046         * Returns true if the current day is <em>Erev Rosh Chodesh</em>. Returns false for <em>Erev Rosh Hashana</em>.
1047         * 
1048         * @return true if the current day is <em>Erev Rosh Chodesh</em>. Returns false for <em>Erev Rosh Hashana</em>.
1049         * @see #isRoshChodesh()
1050         */
1051        public boolean isErevRoshChodesh() {
1052                // Erev Rosh Hashana is not Erev Rosh Chodesh.
1053                return (getJewishDayOfMonth() == 29 && getJewishMonth() != ELUL);
1054        }
1055        
1056        
1057        /**
1058         * Returns true if the current day is <em>Yom Kippur Katan</em>. Returns false for <em>Erev Rosh Hashana</em>,
1059         * <em>Erev Rosh Chodesh Cheshvan</em>, <em>Teves</em> and <em>Iyyar</em>. If <em>Erev Rosh Chodesh</em> occurs
1060         * on a Friday or <em>Shabbos</em>, <em>Yom Kippur Katan</em> is moved back to Thursday.
1061         * 
1062         * @return true if the current day is <em>Erev Rosh Chodesh</em>. Returns false for <em>Erev Rosh Hashana</em>.
1063         * @see #isRoshChodesh()
1064         */
1065        public boolean isYomKippurKatan() {
1066                int dayOfWeek = getDayOfWeek();
1067                int month = getJewishMonth();
1068                int day = getJewishDayOfMonth();
1069                if (month == JewishDate.ELUL || month == JewishDate.TISHREI || month == JewishDate.KISLEV || month == JewishDate.NISSAN) {
1070                        return false;
1071                }
1072
1073                if (day == 29 && dayOfWeek != Calendar.FRIDAY && dayOfWeek != Calendar.SATURDAY) {
1074                        return true;
1075                }
1076                return (day == 27 || day == 28) && dayOfWeek == Calendar.THURSDAY;
1077        }
1078        
1079        /**
1080         * The Monday, Thursday and Monday after the first <em>Shabbos</em> after {@link #isRoshChodesh() <em>Rosh Chodesh</em>}
1081         * {@link JewishDate#CHESHVAN <em>Cheshvan</em>} and {@link JewishDate#IYAR <em>Iyar</em>} are <a href=
1082         * "https://outorah.org/p/41334/"> <em>BeHaB</em></a> days. If the last Monday of Iyar's BeHaB coincides with {@link
1083         * #PESACH_SHENI <em>Pesach Sheni</em>}, the method currently considers it both <em>Pesach Sheni</em> and <em>BeHaB</em>.
1084         * As seen in an Ohr Sameach  article on the subject <a href="https://ohr.edu/this_week/insights_into_halacha/9340">The
1085         * unknown Days: BeHaB Vs. Pesach Sheini?</a> there are some customs that delay the day to various points in the future.
1086         * @return true if the day is <em>BeHaB</em>.
1087         */
1088        public boolean isBeHaB() {
1089                int dayOfWeek = getDayOfWeek();
1090                int month = getJewishMonth();
1091                int day = getJewishDayOfMonth();
1092                
1093                if (month == JewishDate.CHESHVAN || month == JewishDate.IYAR) {
1094                        return (dayOfWeek == Calendar.MONDAY && day > 4 && day < 18)
1095                                        || (dayOfWeek == Calendar.THURSDAY && day > 7 && day < 14);
1096                }
1097                return false;
1098        }
1099
1100        /**
1101         * Return true if the day is a Taanis (fast day). Return true for <em>17 of Tammuz</em>, <em>Tisha B'Av</em>,
1102         * <em>Yom Kippur</em>, <em>Fast of Gedalyah</em>, <em>10 of Teves</em> and the <em>Fast of Esther</em>.
1103         * 
1104         * @return true if today is a fast day
1105         */
1106        public boolean isTaanis() {
1107                int holidayIndex = getYomTovIndex();
1108                return holidayIndex == SEVENTEEN_OF_TAMMUZ || holidayIndex == TISHA_BEAV || holidayIndex == YOM_KIPPUR
1109                                || holidayIndex == FAST_OF_GEDALYAH || holidayIndex == TENTH_OF_TEVES || holidayIndex == FAST_OF_ESTHER;
1110        }
1111        
1112        /**
1113         * Return true if the day is <em>Taanis Bechoros</em> (on <em>Erev Pesach</em>). It will return true for the 14th
1114         * of <em>Nissan</em> if it is not on <em>Shabbos</em>, or if the 12th of <em>Nissan</em> occurs on a Thursday.
1115         * 
1116         * @return true if today is <em>Taanis Bechoros</em>.
1117         */
1118        public boolean isTaanisBechoros() {
1119            final int day = getJewishDayOfMonth();
1120            final int dayOfWeek = getDayOfWeek();
1121            // on 14 Nissan unless that is Shabbos where the fast is moved back to Thursday
1122            return getJewishMonth() == NISSAN && ((day == 14 && dayOfWeek != Calendar.SATURDAY) ||
1123                        (day == 12 && dayOfWeek == Calendar.THURSDAY ));
1124        }
1125
1126        /**
1127         * Returns the day of <em>Chanukah</em> or -1 if it is not <em>Chanukah</em>.
1128         * 
1129         * @return the day of <em>Chanukah</em> or -1 if it is not <em>Chanukah</em>.
1130         * @see #isChanukah()
1131         */
1132        public int getDayOfChanukah() {
1133                final int day = getJewishDayOfMonth();
1134                if (isChanukah()) {
1135                        if (getJewishMonth() == KISLEV) {
1136                                return day - 24;
1137                        } else { // teves
1138                                return isKislevShort() ? day + 5 : day + 6;
1139                        }
1140                } else {
1141                        return -1;
1142                }
1143        }
1144
1145        /**
1146         * Returns true if the current day is one of the 8 days of <em>Chanukah</em>.
1147         * 
1148         * @return if the current day is one of the 8 days of <em>Chanukah</em>.
1149         * 
1150         * @see #getDayOfChanukah()
1151         */
1152        public boolean isChanukah() {
1153                return getYomTovIndex() == CHANUKAH;
1154        }
1155        
1156        /**
1157         * Returns if the day is Purim (<a href="https://en.wikipedia.org/wiki/Purim#Shushan_Purim">Shushan Purim</a>
1158         * in a mukaf choma and regular Purim in a non-mukaf choma). 
1159         * @return if the day is Purim (Shushan Purim in a mukaf choma and regular Purim in a non-mukaf choma)
1160         * 
1161         * @see #getIsMukafChoma()
1162         * @see #setIsMukafChoma(boolean)
1163         */
1164        public boolean isPurim() {
1165                if (isMukafChoma) {
1166                        return getYomTovIndex() == SHUSHAN_PURIM;
1167                } else {
1168                        return getYomTovIndex() == PURIM;
1169                }
1170        }
1171
1172        /**
1173         * Returns if the day is Rosh Chodesh. Rosh Hashana will return false
1174         * 
1175         * @return true if it is Rosh Chodesh. Rosh Hashana will return false
1176         */
1177        public boolean isRoshChodesh() {
1178                // Rosh Hashana is not rosh chodesh. Elul never has 30 days
1179                return (getJewishDayOfMonth() == 1 && getJewishMonth() != TISHREI) || getJewishDayOfMonth() == 30;
1180        }
1181
1182        /**
1183         * Returns if the day is <em>Shabbos</em> and Sunday is <em>Rosh Chodesh</em>.
1184         *
1185         * @return true if it is <em>Shabbos</em> and Sunday is <em>Rosh Chodesh</em>.
1186         * @todo There is more to tweak in this method (it does not cover all cases and opinions), and it may be removed.
1187         */
1188        public boolean isMacharChodesh() {
1189                return (getDayOfWeek() == Calendar.SATURDAY && (getJewishDayOfMonth() == 30 || getJewishDayOfMonth() == 29));
1190        }
1191
1192        /**
1193         * Returns if the day is <em>Shabbos Mevorchim</em>.
1194         *
1195         * @return true if it is <em>Shabbos Mevorchim</em>.
1196         */
1197        public boolean isShabbosMevorchim() {
1198                return (getDayOfWeek() == Calendar.SATURDAY && getJewishDayOfMonth() >= 23 && getJewishDayOfMonth() <= 29 && getJewishMonth() != ELUL);
1199        }
1200
1201        /**
1202         * Returns the int value of the <em>Omer</em> day or -1 if the day is not in the <em>Omer</em>.
1203         * 
1204         * @return The <em>Omer</em> count as an int or -1 if it is not a day of the <em>Omer</em>.
1205         */
1206        public int getDayOfOmer() {
1207                int omer = -1; // not a day of the Omer
1208                int month = getJewishMonth();
1209                int day = getJewishDayOfMonth();
1210
1211                // if Nissan and second day of Pesach and on
1212                if (month == NISSAN && day >= 16) {
1213                        omer = day - 15;
1214                        // if Iyar
1215                } else if (month == IYAR) {
1216                        omer = day + 15;
1217                        // if Sivan and before Shavuos
1218                } else if (month == SIVAN && day < 6) {
1219                        omer = day + 44;
1220                }
1221                return omer;
1222        }
1223        
1224        /**
1225         * Returns if the day is Tisha Be'Av (the 9th of Av).
1226         * @return if the day is Tisha Be'Av (the 9th of Av).
1227         */
1228        public boolean isTishaBav() {
1229            int holidayIndex = getYomTovIndex();
1230            return holidayIndex == TISHA_BEAV;
1231        }
1232
1233        /**
1234         * Returns the <em>molad</em> in Standard Time in Yerushalayim as a Date. The traditional calculation uses local time.
1235         * This method subtracts 20.94 minutes (20 minutes and 56.496 seconds) from the local time (of <em>Har Habayis</em>
1236         * with a longitude of 35.2354&deg; is 5.2354&deg; away from the %15 timezone longitude) to get to standard time. This
1237         * method intentionally uses standard time and not daylight savings time. Java will implicitly format the time to the
1238         * default (or set) Timezone.
1239         * 
1240         * @return the Date representing the moment of the <em>molad</em> in Yerushalayim standard time (GMT + 2)
1241         */
1242        public Instant getMoladAsInstant() {
1243            JewishDate molad = getMolad();
1244
1245            // Standard time offset for Jerusalem: GMT+2
1246            // The raw point in time must be generated using standard time. Using "Asia/Jerusalem" timezone will result in the time
1247            // being incorrectly off by an hour in the summer due to DST. Proper adjustment for the actual time in DST will be done
1248            // by the formatter class used to display the Instant.
1249            ZoneId jerusalemStandardOffset = ZoneId.of("GMT+2");
1250
1251            double moladSeconds = molad.getMoladChalakim() * 10.0 / 3.0; // Compute molad seconds from chalakim
1252            int seconds = (int) moladSeconds;
1253            int nanos = (int) ((moladSeconds - seconds) * 1_000_000_000); // convert remainder to nanos
1254
1255        LocalTime time = LocalTime.of(molad.getMoladHours(),molad.getMoladMinutes(),seconds,nanos);
1256
1257            ZonedDateTime moladZdt = ZonedDateTime.of(molad.getLocalDate(),time,jerusalemStandardOffset);
1258
1259            // Har Habayis at a longitude of 35.2354 offset vs longitude 35 in standard time, so we subtract the time difference
1260            // of 20.94 minutes (20 minutes and 56 seconds and 496 millis) to get to Standard time from local mean time
1261            Duration jerusalemStandardTimeOffset = Duration.ofMinutes(20)
1262                    .plusSeconds(56)
1263                    .plusMillis(496);
1264
1265            return moladZdt.toInstant().minus(jerusalemStandardTimeOffset);
1266        }
1267
1268        /**
1269         * Returns the earliest time of <em>Kiddush Levana</em> calculated as 3 days after the molad. This method returns the time
1270         * even if it is during the day when <em>Kiddush Levana</em> can't be said. Callers of this method should consider
1271         * displaying the next <em>tzais</em> if the <em>zman</em> is between <em>alos</em> and <em>tzais</em>.
1272         * 
1273         * @return the Date representing the moment 3 days after the molad.
1274         * 
1275         * @see com.kosherjava.zmanim.ComprehensiveZmanimCalendar#getTchilasZmanKidushLevana3Days()
1276         * @see com.kosherjava.zmanim.ComprehensiveZmanimCalendar#getTchilasZmanKidushLevana3Days(Instant, Instant)
1277         */
1278        public Instant getTchilasZmanKidushLevana3Days() {
1279            return getMoladAsInstant().plus(Duration.ofHours(72)); // 3 days after the molad
1280        }
1281
1282        /**
1283         * Returns the earliest time of <em>Kiddush Levana</em> calculated as 7 days after the <em>molad</em> as mentioned
1284         * by the <a href="http://en.wikipedia.org/wiki/Yosef_Karo">Mechaber</a>. See the <a
1285         * href="http://en.wikipedia.org/wiki/Yoel_Sirkis">Bach's</a> opinion on this time. This method returns the time
1286         * even if it is during the day when <em>Kiddush Levana</em> can't be said. Callers of this method should consider
1287         * displaying the next <em>tzais</em> if the <em>zman</em> is between <em>alos</em> and <em>tzais</em>.
1288         * 
1289         * @return the Date representing the moment 7 days after the molad.
1290         * 
1291         * @see com.kosherjava.zmanim.ComprehensiveZmanimCalendar#getTchilasZmanKidushLevana7Days()
1292         * @see com.kosherjava.zmanim.ComprehensiveZmanimCalendar#getTchilasZmanKidushLevana7Days(Instant, Instant)
1293         */
1294        public Instant getTchilasZmanKidushLevana7Days() {
1295            return getMoladAsInstant().plus(Duration.ofHours(168)); // 7 days after the molad
1296        }
1297
1298        /**
1299         * Returns the latest time of Kiddush Levana according to the <a
1300         * href="http://en.wikipedia.org/wiki/Yaakov_ben_Moshe_Levi_Moelin">Maharil's</a> opinion that it is calculated as
1301         * halfway between <em>molad</em> and <em>molad</em>. This adds half the 29 days, 12 hours and 793 <em>chalakim</em>
1302         * time between <em>molad</em> and <em>molad</em> (14 days, 18 hours, 22 minutes and 666 milliseconds) to the month's
1303         * <em>molad</em>. This method returns the time even if it is during the day when <em>Kiddush Levana</em> can't be
1304         * recited. Callers of this method should consider displaying <em>alos</em> before this time if the <em>zman</em> is
1305         * between <em>alos</em> and <em>tzais</em>.
1306         * 
1307         * @return the Date representing the moment halfway between <em>molad</em> and <em>molad</em>.
1308         * 
1309         * @see #getSofZmanKidushLevana15Days()
1310         * @see com.kosherjava.zmanim.ComprehensiveZmanimCalendar#getSofZmanKidushLevanaBetweenMoldos()
1311         * @see com.kosherjava.zmanim.ComprehensiveZmanimCalendar#getSofZmanKidushLevanaBetweenMoldos(Instant, Instant)
1312         */
1313        public Instant getSofZmanKidushLevanaBetweenMoldos() {
1314            Instant molad = getMoladAsInstant();
1315
1316            // Duration for half of the lunar month:
1317            // 14 days, 18 hours, 22 minutes, 1 second, 666 milliseconds
1318            Duration halfLunarMonth = Duration.ofDays(14)
1319                    .plusHours(18)
1320                    .plusMinutes(22)
1321                    .plusSeconds(1)
1322                    .plusMillis(666);
1323
1324            return molad.plus(halfLunarMonth);
1325        }
1326
1327        /**
1328         * Returns the latest time of <em>Kiddush Levana</em> calculated as 15 days after the <em>molad.</em> This is the
1329         * opinion brought down in the Shulchan Aruch (Orach Chaim 426). It should be noted that some opinions hold that
1330         * the <a href="http://en.wikipedia.org/wiki/Moses_Isserles">Rema</a> who brings down the <a
1331         * href="http://en.wikipedia.org/wiki/Yaakov_ben_Moshe_Levi_Moelin">Maharil's</a> opinion of calculating it as
1332         * {@link #getSofZmanKidushLevanaBetweenMoldos() half way between <em>molad</em> and <em>molad</em>} is of the
1333         * opinion of the Mechaber as well. Also see the Aruch Hashulchan. For additional details on the subject, See Rabbi
1334         * Dovid Heber's very detailed writeup in Siman Daled (chapter 4) of <a
1335         * href="http://www.worldcat.org/oclc/461326125">Shaarei Zmanim</a>. This method returns the time even if it is during
1336         * the day when <em>Kiddush Levana</em> can't be said. Callers of this method should consider displaying <em>alos</em>
1337         * before this time if the <em>zman</em> is between <em>alos</em> and <em>tzais</em>.
1338         * 
1339         * @return the Date representing the moment 15 days after the <em>molad</em>.
1340         * @see #getSofZmanKidushLevanaBetweenMoldos()
1341         * @see com.kosherjava.zmanim.ComprehensiveZmanimCalendar#getSofZmanKidushLevana15Days()
1342         * @see com.kosherjava.zmanim.ComprehensiveZmanimCalendar#getSofZmanKidushLevana15Days(Instant, Instant)
1343         */
1344        public Instant getSofZmanKidushLevana15Days() {
1345            return getMoladAsInstant().plus(Duration.ofHours(24 * 15));
1346        }
1347
1348        /**
1349         * Returns the <em>Daf Yomi (Bavli)</em> for the date that the calendar is set to. See the
1350         * {@link HebrewDateFormatter#formatDafYomiBavli(Daf)} for the ability to format the <em>daf</em> in
1351         * Hebrew or transliterated <em>masechta</em> names.
1352         * 
1353         * @return the daf as a {@link Daf}
1354         */
1355        public Daf getDafYomiBavli() {
1356                return YomiCalculator.getDafYomiBavli(this);
1357        }
1358        /**
1359         * Returns the <em>Daf Yomi (Yerushalmi)</em> for the date that the calendar is set to. See the
1360         * {@link HebrewDateFormatter#formatDafYomiYerushalmi(Daf)} for the ability to format the <em>daf</em>
1361         * in Hebrew or transliterated <em>masechta</em> names.
1362         *
1363         * @return the daf as a {@link Daf}
1364         */
1365        public Daf getDafYomiYerushalmi() {
1366                return YerushalmiYomiCalculator.getDafYomiYerushalmi(this);
1367        }
1368        
1369        /**
1370         * Returns the elapsed days since <em>Tekufas Tishrei</em>. This uses <em>Tekufas Shmuel</em> (identical to the <a href=
1371         * "https://en.wikipedia.org/wiki/Julian_year_(astronomy)">Julian Year</a> with a solar year length of 365.25 days).
1372         * The notation used below is D = days, H = hours and C = chalakim. <em><a href="https://en.wikipedia.org/wiki/Molad"
1373         * >Molad</a> BaHaRad</em> was 2D,5H,204C or 5H,204C from the start of <em>Rosh Hashana</em> year 1. For <em>molad
1374         * Nissan</em> add 177D, 4H and 438C (6 * 29D, 12H and 793C), or 177D,9H,642C after <em>Rosh Hashana</em> year 1.
1375         * <em>Tekufas Nissan</em> was 7D, 9H and 642C before <em>molad Nissan</em> according to the Rambam, or 170D, 0H and
1376         * 0C after <em>Rosh Hashana</em> year 1. <em>Tekufas Tishrei</em> was 182D and 3H (365.25 / 2) before <em>tekufas
1377         * Nissan</em>, or 12D and 15H before <em>Rosh Hashana</em> of year 1. Outside of Israel we start reciting <em>Tal
1378         * Umatar</em> in <em>Birkas Hashanim</em> from 60 days after <em>tekufas Tishrei</em>. The 60 days include the day of
1379         * the <em>tekufah</em> and the day we start reciting <em>Tal Umatar</em>. 60 days from the tekufah == 47D and 9H
1380         * from <em>Rosh Hashana</em> year 1.
1381         * 
1382         * @return the number of elapsed days since <em>tekufas Tishrei</em>.
1383         * 
1384         * @see com.kosherjava.zmanim.hebrewcalendar.TefilaRules#isVeseinTalUmatarStartDate(JewishCalendar)
1385         * @see com.kosherjava.zmanim.hebrewcalendar.TefilaRules#isVeseinTalUmatarStartingTonight(JewishCalendar)
1386         * @see com.kosherjava.zmanim.hebrewcalendar.TefilaRules#isYaalehVeyavoRecited(JewishCalendar)
1387         * @see #getTekufa()
1388         * @see #getTekufaAsInstant(boolean)
1389         */
1390        public int getTekufasTishreiElapsedDays() {
1391                // Days since Rosh Hashana year 1. Add 1/2 day as the first tekufas tishrei was 9 hours into the day. This allows all
1392                // 4 years of the secular leap year cycle to share 47 days. Truncate 47D and 9H to 47D for simplicity.
1393                double days = getJewishCalendarElapsedDays(getJewishYear()) + (getDaysSinceStartOfJewishYear()-1) + 0.5;
1394                // days of completed solar years
1395                double solar = (getJewishYear() - 1) * 365.25;
1396                return (int) Math.floor(days - solar);
1397        }
1398
1399        /**
1400         * Calculates the hours for when the <a href="https://en.wikipedia.org/wiki/Tekufah"><em>Tekufa</em></a> (season) changes.
1401         * There are 4 <em>tekufos</em> a year: Nissan/Spring, Tammuz/Summer, Tishri/Fall, and Teves/Winter. This calculation is
1402         * according to <a href="https://en.wikipedia.org/wiki/Samuel_of_Nehardea">Shmuel</a> in <a href=
1403         * "https://hebrewbooks.org/shas.aspx?mesechta=3&daf=56">Eruvin 56a</a>, which is a more rounded up version of <a href=
1404         * "https://en.wikipedia.org/wiki/Adda_bar_Ahavah">Rav Adda's</a> calculation. This calculation follows the Levush in the end of Siman 428,
1405         * who writes that the hours to calculate the tekufa are based on regular clock hours and not proportional hours, and that the time
1406         * for the tekufa are based on 6 hours after the previous day's Midday. The <a href=
1407         * "https://en.wikipedia.org/wiki/Moses_Isserles">Rama</a> writes in <a href=
1408         * "https://hebrewbooks.org/pdfpager.aspx?req=67715&st=&pgnum=218">Yoreh De'ah 116:5</a> that one should not drink water during
1409         * the <em>tekufa</em> change. <a href="https://en.wikipedia.org/wiki/Ovadia_Yosef">Rabbi Ovadia Yosef</a> (Halichot Olam,
1410         * Chelek 7, Page 183) recommends to abstain from drinking water for a range of 1 hour (30 minutes before and after the
1411         * <em>tekufa</em> event).
1412         *
1413         * @return the number of hours into the Hebrew day that the <em>tekufa</em> (season) change takes place as a {code Double}, or
1414         *         {@code null} if the <em>tekufa</em> does not occur on current day. For example: 19.5 would mean that the
1415         *         <em>tekufa</em> occurs 19 hours and a half into the Hebrew date, or 13 and a half hours (-6 hours) into the Gregorian
1416         *         date.
1417         */
1418        private Double getTekufa() {
1419                double INITIAL_TEKUFA_OFFSET = 12.625;  // the number of days Tekufas Tishrei occurs before JEWISH_EPOCH
1420
1421                double days = getJewishCalendarElapsedDays(getJewishYear()) + getDaysSinceStartOfJewishYear() + INITIAL_TEKUFA_OFFSET - 1;  // total days since first Tekufas Tishrei event
1422
1423                double solarDaysElapsed = days % 365.25;  // total days elapsed since the start of solar year
1424                double tekufaDaysElapsed = solarDaysElapsed % 91.3125;  // the number of days that have passed since a tekufa event
1425                if (tekufaDaysElapsed > 0 && tekufaDaysElapsed <= 1) {  // if the tekufa happens in the upcoming 24 hours
1426                        return ((1.0 - tekufaDaysElapsed) * 24.0) % 24;// rationalize the tekufa event to number of hours since start of jewish day
1427                } else {
1428                        return null;
1429                }
1430        }
1431
1432        /**
1433         * Returns an {@code Instant} if the current day has a <a href="https://en.wikipedia.org/wiki/Tekufah"><em>Tekufa</em></a>
1434         * (season) change. The {@code Instant} will contain the time that the <em>tekufa</em> (season) is arriving. If this method is
1435         * called on a day without a <em>tekufa</em> change, it will return a {@code null}. The default implementation of this method
1436         * will return the <em>tekufa</em> change according to the calculations of the <a href="https://zmanim.online/">Luach Itim
1437         * Lebinah</a> following <a href="https://en.wikipedia.org/wiki/Yechiel_Michel_Tucazinsky">Rabbi Yechiel Michel Tucazinsky</a>.
1438         * However, there is also the opinion of <a href=
1439         * "https://he.wikipedia.org/wiki/%D7%99%D7%95%D7%A0%D7%94_%D7%9E%D7%A8%D7%A6%D7%91%D7%9A">Rabbi Yonah Merzbach</a>, who
1440         * calculates the <em>tekufa</em> based on Local Mean Time (LMT) in Israel which causes a ~21-minute difference. It should be
1441         * noted that this method only covers two opinions of how to calculate the tekufa (based on 6 hours after Midday of the day
1442         * before the tekufa). The <a href="https://en.wikipedia.org/wiki/Asher_ben_Jehiel">Rosh</a> (Tosafos HaRosh <a href=
1443         * "https://www.sefaria.org/Tosafot_HaRosh_on_Berakhot.3b.6?lang=he">Berachos 3b</a>) is of the opinion that the calculation
1444         * starts at sunset and to use proportional hours. While the <a href="https://en.wikipedia.org/wiki/Simeon_ben_Zemah_Duran"
1445         * >Tashbetz</a> (Shut Tashbetz <a href="https://hebrewbooks.org/pdfpager.aspx?req=1381&st=&pgnum=91">Chelek 1, Siman 109</a>)
1446         * is also of the opinion that the calculation starts at sunset, however, his opinion is to use regular hours.
1447         * @param useLocalMeanTime if true, removes ~21 minutes from the time of the <em>tekufa</em> calculated by Rabbi Yechiel Michel
1448         *         Tucazinsky, and will follow the opinion of Rabbi Yonah Merzbach.
1449         * @return an Instant with the time that the <em>tekufa</em> (season) changes or a {@code null} on a day with no <em>tekufa</em>
1450         *         change.
1451         * @see #getTekufa()
1452         */
1453        public Instant getTekufaAsInstant(boolean useLocalMeanTime) {
1454                Double hours = getTekufa();
1455                if (hours == null) {
1456                        return null;
1457                }
1458                // The tekufa Date must be generated using standard time. Using "Asia/Jerusalem" timezone will result in the time being
1459                // incorrectly off by an hour in the summer due to DST. Proper adjustment for the actual time in DST will be done by the
1460                // formatter class used to display the Instant.
1461                ZoneId yerushalayimStandardTZ = ZoneId.of("GMT+2");
1462
1463                hours -= 6; // minus 6 hours because the hebrew date starts at sunset which is at 6PM
1464
1465                LocalDate tekufaDate = getLocalDate();
1466                if (hours < 0) {
1467                        hours += 24;
1468                        tekufaDate = tekufaDate.minusDays(1);
1469                }
1470
1471                int minutes = (int) ((hours - hours.intValue()) * 60);
1472
1473                LocalTime time = LocalTime.of(hours.intValue(), minutes);
1474                ZonedDateTime tekufaZDT = ZonedDateTime.of(tekufaDate, time, yerushalayimStandardTZ);
1475
1476                // Har Habayis at a longitude of 35.2354 offset vs longitude 35 in standard time, so we subtract the time difference
1477            // of 20.94 minutes (20 minutes and 56 seconds and 496 millis) to get to Standard time from local mean time
1478                if (useLocalMeanTime) {
1479                        Duration jerusalemStandardTimeOffset = Duration.ofMinutes(20)
1480                                        .plusSeconds(56)
1481                                        .plusMillis(496);
1482                        return tekufaZDT.minus(jerusalemStandardTimeOffset).toInstant();
1483                } else {
1484                        return tekufaZDT.toInstant();
1485                }
1486        }
1487        
1488        /**
1489         * Returns true if the current day is <em>Isru Chag</em>. The method returns true for the day following <em>Pesach</em>
1490         * <em>Shavuos</em> and <em>Succos</em>. It utilizes {@see #getInIsrael()} to return the proper date.
1491         * 
1492         * @return true if the current day is <em>Isru Chag</em>. The method returns true for the day following <em>Pesach</em>
1493         * <em>Shavuos</em> and <em>Succos</em>. It utilizes {@see #getInIsrael()} to return the proper date.
1494         */
1495        public boolean isIsruChag() {
1496                int holidayIndex = getYomTovIndex();
1497                return holidayIndex == ISRU_CHAG;
1498        }
1499
1500        /**
1501         * Indicates whether some other object is "equal to" this one.
1502         * @see Object#equals(Object)
1503         */
1504        public boolean equals(Object object) {
1505                if (this == object) {
1506                        return true;
1507                }
1508        if (object == null || getClass() != object.getClass()) {
1509            return false;
1510        }
1511                JewishCalendar jewishCalendar = (JewishCalendar) object;
1512                return getAbsDate() == jewishCalendar.getAbsDate() && getInIsrael() == jewishCalendar.getInIsrael();
1513        }
1514
1515        /**
1516         * Overrides {@link Object#hashCode()}.
1517         * @see Object#hashCode()
1518         */
1519        public int hashCode() {
1520        int result = Integer.hashCode(getAbsDate());
1521        result = 31 * result + Boolean.hashCode(getInIsrael());
1522        return result;
1523        }
1524}