001/*
002 * Zmanim Java API
003 * Copyright (C) 2011 - 2021 Eliyahu Hershfeld
004 * Copyright (C) September 2002 Avrom Finkelstien
005 *
006 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
007 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
008 * any later version.
009 *
010 * This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied
011 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
012 * details.
013 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
014 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA,
015 * or connect to: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
016 */
017package com.kosherjava.zmanim.hebrewcalendar;
018
019import java.time.LocalDate;
020import java.util.Date;
021import java.util.Calendar;
022import java.util.GregorianCalendar;
023
024/**
025 * The JewishDate is the base calendar class, that supports maintenance of a {@link java.util.GregorianCalendar}
026 * instance along with the corresponding Jewish date. This class can use the standard Java Date and Calendar
027 * classes for setting and maintaining the dates, but it does not subclass these classes or use them internally
028 * in any calculations. This class also does not have a concept of a time (which the Date class does). Please
029 * note that the calendar does not currently support dates prior to 1/1/1 Gregorian. Also keep in mind that the
030 * Gregorian calendar started on October 15, 1582, so any calculations prior to that are suspect (at least from
031 * a Gregorian perspective). While 1/1/1 Gregorian and forward are technically supported, any calculations prior to <a
032 * href="http://en.wikipedia.org/wiki/Hillel_II">Hillel II's (Hakatan's</a>) calendar (4119 in the Jewish Calendar / 359
033 * CE Julian as recorded by <a href="http://en.wikipedia.org/wiki/Hai_Gaon">Rav Hai Gaon</a>) would be just an
034 * approximation.
035 * 
036 * This open source Java code was written by <a href="http://www.facebook.com/avromf">Avrom Finkelstien</a> from his C++
037 * code. It was refactored to fit the KosherJava Zmanim API with simplification of the code, enhancements and some bug
038 * fixing.
039 * 
040 * Some of Avrom's original C++ code was translated from
041 * <a href="https://web.archive.org/web/20120124134148/http://emr.cs.uiuc.edu/~reingold/calendar.C">C/C++ code</a> in
042 * <a href="http://www.calendarists.com">Calendrical Calculations</a> by Nachum Dershowitz and Edward M.
043 * Reingold, Software-- Practice &amp; Experience, vol. 20, no. 9 (September, 1990), pp. 899- 928. Any method with the mark
044 * "ND+ER" indicates that the method was taken from this source with minor modifications.
045 * 
046 * If you are looking for a class that implements a Jewish calendar version of the Calendar class, one is available from
047 * the <a href="http://site.icu-project.org/" >ICU (International Components for Unicode)</a> project, formerly part of
048 * IBM's DeveloperWorks.
049 * 
050 * @see JewishCalendar
051 * @see HebrewDateFormatter
052 * @see java.util.Date
053 * @see java.util.Calendar
054 * @author &copy; Avrom Finkelstien 2002
055 * @author &copy; Eliyahu Hershfeld 2011 - 2021
056 */
057public class JewishDate implements Comparable<JewishDate>, Cloneable {
058        /**
059         * Value of the month field indicating Nissan, the first numeric month of the year in the Jewish calendar. With the
060         * year starting at {@link #TISHREI}, it would actually be the 7th (or 8th in a {@link #isJewishLeapYear() leap
061         * year}) month of the year.
062         */
063        public static final int NISSAN = 1;
064
065        /**
066         * Value of the month field indicating Iyar, the second numeric month of the year in the Jewish calendar. With the
067         * year starting at {@link #TISHREI}, it would actually be the 8th (or 9th in a {@link #isJewishLeapYear() leap
068         * year}) month of the year.
069         */
070        public static final int IYAR = 2;
071
072        /**
073         * Value of the month field indicating Sivan, the third numeric month of the year in the Jewish calendar. With the
074         * year starting at {@link #TISHREI}, it would actually be the 9th (or 10th in a {@link #isJewishLeapYear() leap
075         * year}) month of the year.
076         */
077        public static final int SIVAN = 3;
078
079        /**
080         * Value of the month field indicating Tammuz, the fourth numeric month of the year in the Jewish calendar. With the
081         * year starting at {@link #TISHREI}, it would actually be the 10th (or 11th in a {@link #isJewishLeapYear() leap
082         * year}) month of the year.
083         */
084        public static final int TAMMUZ = 4;
085
086        /**
087         * Value of the month field indicating Av, the fifth numeric month of the year in the Jewish calendar. With the year
088         * starting at {@link #TISHREI}, it would actually be the 11th (or 12th in a {@link #isJewishLeapYear() leap year})
089         * month of the year.
090         */
091        public static final int AV = 5;
092
093        /**
094         * Value of the month field indicating Elul, the sixth numeric month of the year in the Jewish calendar. With the
095         * year starting at {@link #TISHREI}, it would actually be the 12th (or 13th in a {@link #isJewishLeapYear() leap
096         * year}) month of the year.
097         */
098        public static final int ELUL = 6;
099
100        /**
101         * Value of the month field indicating Tishrei, the seventh numeric month of the year in the Jewish calendar. With
102         * the year starting at this month, it would actually be the 1st month of the year.
103         */
104        public static final int TISHREI = 7;
105
106        /**
107         * Value of the month field indicating Cheshvan/marcheshvan, the eighth numeric month of the year in the Jewish
108         * calendar. With the year starting at {@link #TISHREI}, it would actually be the 2nd month of the year.
109         */
110        public static final int CHESHVAN = 8;
111
112        /**
113         * Value of the month field indicating Kislev, the ninth numeric month of the year in the Jewish calendar. With the
114         * year starting at {@link #TISHREI}, it would actually be the 3rd month of the year.
115         */
116        public static final int KISLEV = 9;
117
118        /**
119         * Value of the month field indicating Teves, the tenth numeric month of the year in the Jewish calendar. With the
120         * year starting at {@link #TISHREI}, it would actually be the 4th month of the year.
121         */
122        public static final int TEVES = 10;
123
124        /**
125         * Value of the month field indicating Shevat, the eleventh numeric month of the year in the Jewish calendar. With
126         * the year starting at {@link #TISHREI}, it would actually be the 5th month of the year.
127         */
128        public static final int SHEVAT = 11;
129
130        /**
131         * Value of the month field indicating Adar (or Adar I in a {@link #isJewishLeapYear() leap year}), the twelfth
132         * numeric month of the year in the Jewish calendar. With the year starting at {@link #TISHREI}, it would actually
133         * be the 6th month of the year.
134         */
135        public static final int ADAR = 12;
136
137        /**
138         * Value of the month field indicating Adar II, the leap (intercalary or embolismic) thirteenth (Undecimber) numeric
139         * month of the year added in Jewish {@link #isJewishLeapYear() leap year}). The leap years are years 3, 6, 8, 11,
140         * 14, 17 and 19 of a 19 year cycle. With the year starting at {@link #TISHREI}, it would actually be the 7th month
141         * of the year.
142         */
143        public static final int ADAR_II = 13;
144
145        /**
146         * the Jewish epoch using the RD (Rata Die/Fixed Date or Reingold Dershowitz) day used in Calendrical Calculations.
147         * Day 1 is January 1, 0001 Gregorian
148         */
149        private static final int JEWISH_EPOCH = -1373429;
150
151        /** The number  of <em>chalakim</em> (18) in a minute.*/
152        private static final int CHALAKIM_PER_MINUTE = 18;
153        /** The number  of <em>chalakim</em> (1080) in an hour.*/
154        private static final int CHALAKIM_PER_HOUR = 1080;
155        /** The number of <em>chalakim</em> (25,920) in a 24 hour day .*/
156        private static final int CHALAKIM_PER_DAY = 25920; // 24 * 1080
157        /** The number  of <em>chalakim</em> in an average Jewish month. A month has 29 days, 12 hours and 793
158         * <em>chalakim</em> (44 minutes and 3.3 seconds) for a total of 765,433 <em>chalakim</em>*/
159        private static final long CHALAKIM_PER_MONTH = 765433; // (29 * 24 + 12) * 1080 + 793
160        /**
161         * Days from the beginning of Sunday till molad BaHaRaD. Calculated as 1 day, 5 hours and 204 chalakim = (24 + 5) *
162         * 1080 + 204 = 31524
163         */
164        private static final int CHALAKIM_MOLAD_TOHU = 31524;
165
166        /**
167         * A short year where both {@link #CHESHVAN} and {@link #KISLEV} are 29 days.
168         * 
169         * @see #getCheshvanKislevKviah()
170         * @see HebrewDateFormatter#getFormattedKviah(int)
171         */
172        public static final int CHASERIM = 0;
173
174        /**
175         * An ordered year where {@link #CHESHVAN} is 29 days and {@link #KISLEV} is 30 days.
176         * 
177         * @see #getCheshvanKislevKviah()
178         * @see HebrewDateFormatter#getFormattedKviah(int)
179         */
180        public static final int KESIDRAN = 1;
181
182        /**
183         * A long year where both {@link #CHESHVAN} and {@link #KISLEV} are 30 days.
184         * 
185         * @see #getCheshvanKislevKviah()
186         * @see HebrewDateFormatter#getFormattedKviah(int)
187         */
188        public static final int SHELAIMIM = 2;
189
190        /** the internal Jewish month.*/
191        private int jewishMonth;
192        /** the internal Jewish day.*/
193        private int jewishDay;
194        /** the internal Jewish year.*/
195        private int jewishYear;
196        /** the internal count of <em>molad</em> hours.*/
197        private int moladHours;
198        /** the internal count of <em>molad</em> minutes.*/
199        private int moladMinutes;
200        /** the internal count of <em>molad</em> <em>chalakim</em>.*/
201        private int moladChalakim;
202
203        /**
204         * Returns the molad hours. Only a JewishDate object populated with {@link #getMolad()},
205         * {@link #setJewishDate(int, int, int, int, int, int)} or {@link #setMoladHours(int)} will have this field
206         * populated. A regular JewishDate object will have this field set to 0.
207         * 
208         * @return the molad hours
209         * @see #setMoladHours(int)
210         * @see #getMolad()
211         * @see #setJewishDate(int, int, int, int, int, int)
212         */
213        public int getMoladHours() {
214                return moladHours;
215        }
216
217        /**
218         * Sets the molad hours.
219         * 
220         * @param moladHours
221         *            the molad hours to set
222         * @see #getMoladHours()
223         * @see #getMolad()
224         * @see #setJewishDate(int, int, int, int, int, int)
225         * 
226         */
227        public void setMoladHours(int moladHours) {
228                this.moladHours = moladHours;
229        }
230
231        /**
232         * Returns the molad minutes. Only an object populated with {@link #getMolad()},
233         * {@link #setJewishDate(int, int, int, int, int, int)} or or {@link #setMoladMinutes(int)} will have these fields
234         * populated. A regular JewishDate object will have this field set to 0.
235         * 
236         * @return the molad minutes
237         * @see #setMoladMinutes(int)
238         * @see #getMolad()
239         * @see #setJewishDate(int, int, int, int, int, int)
240         */
241        public int getMoladMinutes() {
242                return moladMinutes;
243        }
244
245        /**
246         * Sets the molad minutes. The expectation is that the traditional minute-less chalakim will be broken out to
247         * minutes and {@link #setMoladChalakim(int) chalakim/parts} , so 793 (TaShTZaG) parts would have the minutes set to
248         * 44 and chalakim to 1.
249         * 
250         * @param moladMinutes
251         *            the molad minutes to set
252         * @see #getMoladMinutes()
253         * @see #setMoladChalakim(int)
254         * @see #getMolad()
255         * @see #setJewishDate(int, int, int, int, int, int)
256         * 
257         */
258        public void setMoladMinutes(int moladMinutes) {
259                this.moladMinutes = moladMinutes;
260        }
261
262        /**
263         * Sets the molad chalakim/parts. The expectation is that the traditional minute-less chalakim will be broken out to
264         * {@link #setMoladMinutes(int) minutes} and chalakim, so 793 (TaShTZaG) parts would have the minutes set to 44 and
265         * chalakim to 1.
266         * 
267         * @param moladChalakim
268         *            the molad chalakim/parts to set
269         * @see #getMoladChalakim()
270         * @see #setMoladMinutes(int)
271         * @see #getMolad()
272         * @see #setJewishDate(int, int, int, int, int, int)
273         * 
274         */
275        public void setMoladChalakim(int moladChalakim) {
276                this.moladChalakim = moladChalakim;
277        }
278
279        /**
280         * Returns the molad chalakim/parts. Only an object populated with {@link #getMolad()},
281         * {@link #setJewishDate(int, int, int, int, int, int)} or or {@link #setMoladChalakim(int)} will have these fields
282         * populated. A regular JewishDate object will have this field set to 0.
283         * 
284         * @return the molad chalakim/parts
285         * @see #setMoladChalakim(int)
286         * @see #getMolad()
287         * @see #setJewishDate(int, int, int, int, int, int)
288         */
289        public int getMoladChalakim() {
290                return moladChalakim;
291        }
292
293        /**
294         * Returns the last day in a gregorian month
295         * 
296         * @param month
297         *            the Gregorian month
298         * @return the last day of the Gregorian month
299         */
300        int getLastDayOfGregorianMonth(int month) {
301                return getLastDayOfGregorianMonth(month, gregorianYear);
302        }
303
304        /**
305         * Returns is the year passed in is a <a href=
306         * "https://en.wikipedia.org/wiki/Leap_year#Gregorian_calendar">Gregorian leap year</a>.
307         * @param year the Gregorian year
308         * @return if the year in question is a leap year.
309         */
310        boolean isGregorianLeapYear(int year) {
311                return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
312        }
313
314        /**
315         * The month, where 1 == January, 2 == February, etc... Note that this is different than the Java's Calendar class
316         * where January ==0
317         */
318        private int gregorianMonth;
319
320        /** The day of the Gregorian month */
321        private int gregorianDayOfMonth;
322
323        /** The Gregorian year */
324        private int gregorianYear;
325
326        /** 1 == Sunday, 2 == Monday, etc... */
327        private int dayOfWeek;
328
329        /** Returns the absolute date (days since January 1, 0001 on the Gregorian calendar).
330         * @see #getAbsDate()
331         * @see #absDateToJewishDate()
332         */
333        private int gregorianAbsDate;
334
335        /**
336         * Returns the number of days in a given month in a given month and year.
337         * 
338         * @param month
339         *            the month. As with other cases in this class, this is 1-based, not zero-based.
340         * @param year
341         *            the year (only impacts February)
342         * @return the number of days in the month in the given year
343         */
344        private static int getLastDayOfGregorianMonth(int month, int year) {
345                switch (month) {
346                case 2:
347                        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
348                                return 29;
349                        } else {
350                                return 28;
351                        }
352                case 4:
353                case 6:
354                case 9:
355                case 11:
356                        return 30;
357                default:
358                        return 31;
359                }
360        }
361
362        /**
363         * Computes the Gregorian date from the absolute date. ND+ER
364         * @param absDate the absolute date
365         */
366        private void absDateToDate(int absDate) {
367                int year = absDate / 366; // Search forward year by year from approximate year
368                while (absDate >= gregorianDateToAbsDate(year + 1, 1, 1)) {
369                        year++;
370                }
371
372                int month = 1; // Search forward month by month from January
373                while (absDate > gregorianDateToAbsDate(year, month, getLastDayOfGregorianMonth(month, year))) {
374                        month++;
375                }
376
377                int dayOfMonth = absDate - gregorianDateToAbsDate(year, month, 1) + 1;
378                setInternalGregorianDate(year, month, dayOfMonth);
379        }
380
381        /**
382         * Returns the absolute date (days since January 1, 0001 on the Gregorian calendar).
383         * 
384         * @return the number of days since January 1, 1
385         */
386        public int getAbsDate() {
387                return gregorianAbsDate;
388        }
389
390        /**
391         * Computes the absolute date from a Gregorian date. ND+ER
392         * 
393         * @param year
394         *            the Gregorian year
395         * @param month
396         *            the Gregorian month. Unlike the Java Calendar where January has the value of 0,This expects a 1 for
397         *            January
398         * @param dayOfMonth
399         *            the day of the month (1st, 2nd, etc...)
400         * @return the absolute Gregorian day
401         */
402        private static int gregorianDateToAbsDate(int year, int month, int dayOfMonth) {
403                int absDate = dayOfMonth;
404                for (int m = month - 1; m > 0; m--) {
405                        absDate += getLastDayOfGregorianMonth(m, year); // days in prior months of the year
406                }
407                return (absDate // days this year
408                                + 365 * (year - 1) // days in previous years ignoring leap days
409                                + (year - 1) / 4 // Julian leap days before this year
410                                - (year - 1) / 100 // minus prior century years
411                + (year - 1) / 400); // plus prior years divisible by 400
412        }
413
414        /**
415         * Returns if the year is a Jewish leap year. Years 3, 6, 8, 11, 14, 17 and 19 in the 19 year cycle are leap years.
416         * 
417         * @param year
418         *            the Jewish year.
419         * @return true if it is a leap year
420         * @see #isJewishLeapYear()
421         */
422        private static boolean isJewishLeapYear(int year) {
423                return ((7 * year) + 1) % 19 < 7;
424        }
425
426        /**
427         * Returns if the year the calendar is set to is a Jewish leap year. Years 3, 6, 8, 11, 14, 17 and 19 in the 19 year
428         * cycle are leap years.
429         * 
430         * @return true if it is a leap year
431         * @see #isJewishLeapYear(int)
432         */
433        public boolean isJewishLeapYear() {
434                return isJewishLeapYear(getJewishYear());
435        }
436
437        /**
438         * Returns the last month of a given Jewish year. This will be 12 on a non {@link #isJewishLeapYear(int) leap year}
439         * or 13 on a leap year.
440         * 
441         * @param year
442         *            the Jewish year.
443         * @return 12 on a non leap year or 13 on a leap year
444         * @see #isJewishLeapYear(int)
445         */
446        private static int getLastMonthOfJewishYear(int year) {
447                return isJewishLeapYear(year) ? ADAR_II : ADAR;
448        }
449
450        /**
451         * Returns the number of days elapsed from the Sunday prior to the start of the Jewish calendar to the mean
452         * conjunction of Tishri of the Jewish year.
453         * 
454         * @param year
455         *            the Jewish year
456         * @return the number of days elapsed from prior to the molad Tohu BaHaRaD (Be = Monday, Ha= 5 hours and Rad =204
457         *         chalakim/parts) prior to the start of the Jewish calendar, to the mean conjunction of Tishri of the
458         *         Jewish year. BeHaRaD is 23:11:20 on Sunday night(5 hours 204/1080 chalakim after sunset on Sunday
459         *         evening).
460         */
461        public static int getJewishCalendarElapsedDays(int year) {
462                long chalakimSince = getChalakimSinceMoladTohu(year, TISHREI);
463                int moladDay = (int) (chalakimSince / (long) CHALAKIM_PER_DAY);
464                int moladParts = (int) (chalakimSince - moladDay * (long) CHALAKIM_PER_DAY);
465                // delay Rosh Hashana for the 4 dechiyos
466                return addDechiyos(year, moladDay, moladParts);
467        }
468
469        // private static int getJewishCalendarElapsedDaysOLD(int year) {
470        // // Jewish lunar month = 29 days, 12 hours and 793 chalakim
471        // // Molad Tohu = BeHaRaD - Monday, 5 hours (11 PM) and 204 chalakim
472        // final int chalakimTashTZag = 793; // chalakim in a lunar month
473        // final int chalakimTohuRaD = 204; // chalakim from original molad Tohu BeHaRaD
474        // final int hoursTohuHa = 5; // hours from original molad Tohu BeHaRaD
475        // final int dayTohu = 1; // Monday (0 based)
476        //
477        // int monthsElapsed = (235 * ((year - 1) / 19)) // Months in complete 19 year lunar (Metonic) cycles so far
478        // + (12 * ((year - 1) % 19)) // Regular months in this cycle
479        // + ((7 * ((year - 1) % 19) + 1) / 19); // Leap months this cycle
480        // // start with Molad Tohu BeHaRaD
481        // // start with RaD of BeHaRaD and add TaShTzaG (793) chalakim plus elapsed chalakim
482        // int partsElapsed = chalakimTohuRaD + chalakimTashTZag * (monthsElapsed % 1080);
483        // // start with Ha hours of BeHaRaD, add 12 hour remainder of lunar month add hours elapsed
484        // int hoursElapsed = hoursTohuHa + 12 * monthsElapsed + 793 * (monthsElapsed / 1080) + partsElapsed / 1080;
485        // // start with Monday of BeHaRaD = 1 (0 based), add 29 days of the lunar months elapsed
486        // int conjunctionDay = dayTohu + 29 * monthsElapsed + hoursElapsed / 24;
487        // int conjunctionParts = 1080 * (hoursElapsed % 24) + partsElapsed % 1080;
488        // return addDechiyos(year, conjunctionDay, conjunctionParts);
489        // }
490
491        /**
492         * Adds the 4 dechiyos for molad Tishrei. These are:
493         * <ol>
494         * <li>Lo ADU Rosh - Rosh Hashana can't fall on a Sunday, Wednesday or Friday. If the molad fell on one of these
495         * days, Rosh Hashana is delayed to the following day.</li>
496         * <li>Molad Zaken - If the molad of Tishrei falls after 12 noon, Rosh Hashana is delayed to the following day. If
497         * the following day is ADU, it will be delayed an additional day.</li>
498         * <li>GaTRaD - If on a non leap year the molad of Tishrei falls on a Tuesday (Ga) on or after 9 hours (T) and 204
499         * chalakim (TRaD) it is delayed till Thursday (one day delay, plus one day for Lo ADU Rosh)</li>
500         * <li>BeTuTaKFoT - if the year following a leap year falls on a Monday (Be) on or after 15 hours (Tu) and 589
501         * chalakim (TaKFoT) it is delayed till Tuesday</li>
502         * </ol>
503         * 
504         * @param year the year
505         * @param moladDay the molad day
506         * @param moladParts the molad parts
507         * @return the number of elapsed days in the JewishCalendar adjusted for the 4 dechiyos.
508         */
509        private static int addDechiyos(int year, int moladDay, int moladParts) {
510                int roshHashanaDay = moladDay; // if no dechiyos
511                // delay Rosh Hashana for the dechiyos of the Molad - new moon 1 - Molad Zaken, 2- GaTRaD 3- BeTuTaKFoT
512                if ((moladParts >= 19440) // Dechiya of Molad Zaken - molad is >= midday (18 hours * 1080 chalakim)
513                                || (((moladDay % 7) == 2) // start Dechiya of GaTRaD - Ga = is a Tuesday
514                                                && (moladParts >= 9924) // TRaD = 9 hours, 204 parts or later (9 * 1080 + 204)
515                                && !isJewishLeapYear(year)) // of a non-leap year - end Dechiya of GaTRaD
516                                || (((moladDay % 7) == 1) // start Dechiya of BeTuTaKFoT - Be = is on a Monday
517                                                && (moladParts >= 16789) // TRaD = 15 hours, 589 parts or later (15 * 1080 + 589)
518                                && (isJewishLeapYear(year - 1)))) { // in a year following a leap year - end Dechiya of BeTuTaKFoT
519                        roshHashanaDay += 1; // Then postpone Rosh HaShanah one day
520                }
521                // start 4th Dechiya - Lo ADU Rosh - Rosh Hashana can't occur on A- sunday, D- Wednesday, U - Friday
522                if (((roshHashanaDay % 7) == 0)// If Rosh HaShanah would occur on Sunday,
523                                || ((roshHashanaDay % 7) == 3) // or Wednesday,
524                                || ((roshHashanaDay % 7) == 5)) { // or Friday - end 4th Dechiya - Lo ADU Rosh
525                        roshHashanaDay = roshHashanaDay + 1; // Then postpone it one (more) day
526                }
527                return roshHashanaDay;
528        }
529
530        /**
531         * Returns the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu to the year
532         * and month passed in.
533         * 
534         * @param year
535         *            the Jewish year
536         * @param month
537         *            the Jewish month the Jewish month, with the month numbers starting from Nisan. Use the JewishDate
538         *            constants such as {@link JewishDate#TISHREI}.
539         * @return the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu
540         */
541        private static long getChalakimSinceMoladTohu(int year, int month) {
542                // Jewish lunar month = 29 days, 12 hours and 793 chalakim
543                // chalakim since Molad Tohu BeHaRaD - 1 day, 5 hours and 204 chalakim
544                int monthOfYear = getJewishMonthOfYear(year, month);
545                int monthsElapsed = (235 * ((year - 1) / 19)) // Months in complete 19 year lunar (Metonic) cycles so far
546                                + (12 * ((year - 1) % 19)) // Regular months in this cycle
547                                + ((7 * ((year - 1) % 19) + 1) / 19) // Leap months this cycle
548                                + (monthOfYear - 1); // add elapsed months till the start of the molad of the month
549                // return chalakim prior to BeHaRaD + number of chalakim since
550                return CHALAKIM_MOLAD_TOHU + (CHALAKIM_PER_MONTH * monthsElapsed);
551        }
552
553        /**
554         * Returns the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu to the Jewish
555         * year and month that this Object is set to.
556         * 
557         * @return the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu
558         */
559        public long getChalakimSinceMoladTohu() {
560                return getChalakimSinceMoladTohu(jewishYear, jewishMonth);
561        }
562
563        /**
564         * Converts the {@link JewishDate#NISSAN} based constants used by this class to numeric month starting from
565         * {@link JewishDate#TISHREI}. This is required for Molad claculations.
566         * 
567         * @param year
568         *            The Jewish year
569         * @param month
570         *            The Jewish Month
571         * @return the Jewish month of the year starting with Tishrei
572         */
573        private static int getJewishMonthOfYear(int year, int month) {
574                boolean isLeapYear = isJewishLeapYear(year);
575                return (month + (isLeapYear ? 6 : 5)) % (isLeapYear ? 13 : 12) + 1;
576        }
577
578        /**
579         * Validates the components of a Jewish date for validity. It will throw an {@link IllegalArgumentException} if the
580         * Jewish date is earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month &lt; 1 or &gt; 12 (or 13 on a
581         * {@link #isJewishLeapYear(int) leap year}), the day of month is &lt; 1 or &gt; 30, an hour &lt; 0 or &gt; 23, a minute &lt; 0
582         * or &gt; 59 or chalakim &lt; 0 or &gt; 17. For larger a larger number of chalakim such as 793 (TaShTzaG) break the chalakim into
583         * minutes (18 chalakim per minutes, so it would be 44 minutes and 1 chelek in the case of 793/TaShTzaG).
584         * 
585         * @param year
586         *            the Jewish year to validate. It will reject any year &lt;= 3761 (lower than the year 1 Gregorian).
587         * @param month
588         *            the Jewish month to validate. It will reject a month &lt; 1 or &gt; 12 (or 13 on a leap year) .
589         * @param dayOfMonth
590         *            the day of the Jewish month to validate. It will reject any value &lt; 1 or &gt; 30 TODO: check calling
591         *            methods to see if there is any reason that the class can validate that 30 is invalid for some months.
592         * @param hours
593         *            the hours (for molad calculations). It will reject an hour &lt; 0 or &gt; 23
594         * @param minutes
595         *            the minutes (for molad calculations). It will reject a minute &lt; 0 or &gt; 59
596         * @param chalakim
597         *            the chalakim/parts (for molad calculations). It will reject a chalakim &lt; 0 or &gt; 17. For larger numbers
598         *            such as 793 (TaShTzaG) break the chalakim into minutes (18 chalakim per minutes, so it would be 44
599         *            minutes and 1 chelek in the case of 793/TaShTzaG)
600         * 
601         * @throws IllegalArgumentException
602         *             if a A Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month &lt; 1 or &gt; 12 (or 13 on a
603         *             leap year), the day of month is &lt; 1 or &gt; 30, an hour &lt; 0 or &gt; 23, a minute &lt; 0 or &gt; 59 or
604         *             chalakim &lt; 0 or &gt; 17. For larger a larger number of chalakim such as 793 (TaShTzaG) break the chalakim
605         *             into minutes (18 chalakim per minutes, so it would be 44 minutes and 1 chelek in the case of 793 (TaShTzaG).
606         */
607        private static void validateJewishDate(int year, int month, int dayOfMonth, int hours, int minutes, int chalakim) {
608                if (month < NISSAN || month > getLastMonthOfJewishYear(year)) {
609                        throw new IllegalArgumentException("The Jewish month has to be between 1 and 12 (or 13 on a leap year). "
610                                        + month + " is invalid for the year " + year + ".");
611                }
612                if (dayOfMonth < 1 || dayOfMonth > 30) {
613                        throw new IllegalArgumentException("The Jewish day of month can't be < 1 or > 30.  " + dayOfMonth
614                                        + " is invalid.");
615                }
616                // reject dates prior to 18 Teves, 3761 (1/1/1 AD). This restriction can be relaxed if the date coding is
617                // changed/corrected
618                if ((year < 3761) || (year == 3761 && (month >= TISHREI && month < TEVES))
619                                || (year == 3761 && month == TEVES && dayOfMonth < 18)) {
620                        throw new IllegalArgumentException(
621                                        "A Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian) can't be set. " + year + ", " + month
622                                                        + ", " + dayOfMonth + " is invalid.");
623                }
624                if (hours < 0 || hours > 23) {
625                        throw new IllegalArgumentException("Hours < 0 or > 23 can't be set. " + hours + " is invalid.");
626                }
627
628                if (minutes < 0 || minutes > 59) {
629                        throw new IllegalArgumentException("Minutes < 0 or > 59 can't be set. " + minutes + " is invalid.");
630                }
631
632                if (chalakim < 0 || chalakim > 17) {
633                        throw new IllegalArgumentException(
634                                        "Chalakim/parts < 0 or > 17 can't be set. "
635                                                        + chalakim
636                                                        + " is invalid. For larger numbers such as 793 (TaShTzaG) break the chalakim into minutes (18 chalakim per minutes, so it would be 44 minutes and 1 chelek in the case of 793 (TaShTzaG)");
637                }
638        }
639
640        /**
641         * Validates the components of a Gregorian date for validity. It will throw an {@link IllegalArgumentException} if a
642         * year of &lt; 1, a month &lt; 0 or &gt; 11 or a day of month &lt; 1 is passed in.
643         * 
644         * @param year
645         *            the Gregorian year to validate. It will reject any year &lt; 1.
646         * @param month
647         *            the Gregorian month number to validate. It will enforce that the month is between 0 - 11 like a
648         *            {@link GregorianCalendar}, where {@link Calendar#JANUARY} has a value of 0.
649         * @param dayOfMonth
650         *            the day of the Gregorian month to validate. It will reject any value &lt; 1, but will allow values &gt; 31
651         *            since calling methods will simply set it to the maximum for that month. TODO: check calling methods to
652         *            see if there is any reason that the class needs days &gt; the maximum.
653         * @throws IllegalArgumentException
654         *             if a year of &lt; 1, a month &lt; 0 or &gt; 11 or a day of month &lt; 1 is passed in
655         * @see #validateGregorianYear(int)
656         * @see #validateGregorianMonth(int)
657         * @see #validateGregorianDayOfMonth(int)
658         */
659        private static void validateGregorianDate(int year, int month, int dayOfMonth) {
660                validateGregorianMonth(month);
661                validateGregorianDayOfMonth(dayOfMonth);
662                validateGregorianYear(year);
663        }
664
665        /**
666         * Validates a Gregorian month for validity.
667         * 
668         * @param month
669         *            the Gregorian month number to validate. It will enforce that the month is between 0 - 11 like a
670         *            {@link GregorianCalendar}, where {@link Calendar#JANUARY} has a value of 0.
671         */
672        private static void validateGregorianMonth(int month) {
673                if (month > 11 || month < 0) {
674                        throw new IllegalArgumentException("The Gregorian month has to be between 0 - 11. " + month
675                                        + " is invalid.");
676                }
677        }
678
679        /**
680         * Validates a Gregorian day of month for validity.
681         * 
682         * @param dayOfMonth
683         *            the day of the Gregorian month to validate. It will reject any value &lt; 1, but will allow values &gt; 31
684         *            since calling methods will simply set it to the maximum for that month. TODO: check calling methods to
685         *            see if there is any reason that the class needs days &gt; the maximum.
686         */
687        private static void validateGregorianDayOfMonth(int dayOfMonth) {
688                if (dayOfMonth <= 0) {
689                        throw new IllegalArgumentException("The day of month can't be less than 1. " + dayOfMonth + " is invalid.");
690                }
691        }
692
693        /**
694         * Validates a Gregorian year for validity.
695         * 
696         * @param year
697         *            the Gregorian year to validate. It will reject any year &lt; 1.
698         */
699        private static void validateGregorianYear(int year) {
700                if (year < 1) {
701                        throw new IllegalArgumentException("Years < 1 can't be claculated. " + year + " is invalid.");
702                }
703        }
704
705        /**
706         * Returns the number of days for a given Jewish year. ND+ER
707         * 
708         * @param year
709         *            the Jewish year
710         * @return the number of days for a given Jewish year.
711         * @see #isCheshvanLong()
712         * @see #isKislevShort()
713         */
714        public static int getDaysInJewishYear(int year) {
715                return getJewishCalendarElapsedDays(year + 1) - getJewishCalendarElapsedDays(year);
716        }
717
718        /**
719         * Returns the number of days for the current year that the calendar is set to.
720         * 
721         * @return the number of days for the Object's current Jewish year.
722         * @see #isCheshvanLong()
723         * @see #isKislevShort()
724         * @see #isJewishLeapYear()
725         */
726        public int getDaysInJewishYear() {
727                return getDaysInJewishYear(getJewishYear());
728        }
729
730        /**
731         * Returns if Cheshvan is long in a given Jewish year. The method name isLong is done since in a Kesidran (ordered)
732         * year Cheshvan is short. ND+ER
733         * 
734         * @param year
735         *            the year
736         * @return true if Cheshvan is long in Jewish year.
737         * @see #isCheshvanLong()
738         * @see #getCheshvanKislevKviah()
739         */
740        private static boolean isCheshvanLong(int year) {
741                return getDaysInJewishYear(year) % 10 == 5;
742        }
743
744        /**
745         * Returns if Cheshvan is long (30 days VS 29 days) for the current year that the calendar is set to. The method
746         * name isLong is done since in a Kesidran (ordered) year Cheshvan is short.
747         * 
748         * @return true if Cheshvan is long for the current year that the calendar is set to
749         * @see #isCheshvanLong()
750         */
751        public boolean isCheshvanLong() {
752                return isCheshvanLong(getJewishYear());
753        }
754
755        /**
756         * Returns if Kislev is short (29 days VS 30 days) in a given Jewish year. The method name isShort is done since in
757         * a Kesidran (ordered) year Kislev is long. ND+ER
758         * 
759         * @param year
760         *            the Jewish year
761         * @return true if Kislev is short for the given Jewish year.
762         * @see #isKislevShort()
763         * @see #getCheshvanKislevKviah()
764         */
765        private static boolean isKislevShort(int year) {
766                return getDaysInJewishYear(year) % 10 == 3;
767        }
768
769        /**
770         * Returns if the Kislev is short for the year that this class is set to. The method name isShort is done since in a
771         * Kesidran (ordered) year Kislev is long.
772         * 
773         * @return true if Kislev is short for the year that this class is set to
774         */
775        public boolean isKislevShort() {
776                return isKislevShort(getJewishYear());
777        }
778
779        /**
780         * Returns the Cheshvan and Kislev kviah (whether a Jewish year is short, regular or long). It will return
781         * {@link #SHELAIMIM} if both cheshvan and kislev are 30 days, {@link #KESIDRAN} if Cheshvan is 29 days and Kislev
782         * is 30 days and {@link #CHASERIM} if both are 29 days.
783         * 
784         * @return {@link #SHELAIMIM} if both cheshvan and kislev are 30 days, {@link #KESIDRAN} if Cheshvan is 29 days and
785         *         Kislev is 30 days and {@link #CHASERIM} if both are 29 days.
786         * @see #isCheshvanLong()
787         * @see #isKislevShort()
788         */
789        public int getCheshvanKislevKviah() {
790                if (isCheshvanLong() && !isKislevShort()) {
791                        return SHELAIMIM;
792                } else if (!isCheshvanLong() && isKislevShort()) {
793                        return CHASERIM;
794                } else {
795                        return KESIDRAN;
796                }
797        }
798
799        /**
800         * Returns the number of days of a Jewish month for a given month and year.
801         * 
802         * @param month
803         *            the Jewish month
804         * @param year
805         *            the Jewish Year
806         * @return the number of days for a given Jewish month
807         */
808        private static int getDaysInJewishMonth(int month, int year) {
809                if ((month == IYAR) || (month == TAMMUZ) || (month == ELUL) || ((month == CHESHVAN) && !(isCheshvanLong(year)))
810                                || ((month == KISLEV) && isKislevShort(year)) || (month == TEVES)
811                                || ((month == ADAR) && !(isJewishLeapYear(year))) || (month == ADAR_II)) {
812                        return 29;
813                } else {
814                        return 30;
815                }
816        }
817
818        /**
819         * Returns the number of days of the Jewish month that the calendar is currently set to.
820         * 
821         * @return the number of days for the Jewish month that the calendar is currently set to.
822         */
823        public int getDaysInJewishMonth() {
824                return getDaysInJewishMonth(getJewishMonth(), getJewishYear());
825        }
826
827        /**
828         * Computes the Jewish date from the absolute date.
829         */
830        private void absDateToJewishDate() {
831                // Approximation from below
832                jewishYear = (gregorianAbsDate - JEWISH_EPOCH) / 366;
833                // Search forward for year from the approximation
834                while (gregorianAbsDate >= jewishDateToAbsDate(jewishYear + 1, TISHREI, 1)) {
835                        jewishYear++;
836                }
837                // Search forward for month from either Tishri or Nisan.
838                if (gregorianAbsDate < jewishDateToAbsDate(jewishYear, NISSAN, 1)) {
839                        jewishMonth = TISHREI;// Start at Tishri
840                } else {
841                        jewishMonth = NISSAN;// Start at Nisan
842                }
843                while (gregorianAbsDate > jewishDateToAbsDate(jewishYear, jewishMonth, getDaysInJewishMonth())) {
844                        jewishMonth++;
845                }
846                // Calculate the day by subtraction
847                jewishDay = gregorianAbsDate - jewishDateToAbsDate(jewishYear, jewishMonth, 1) + 1;
848        }
849
850        /**
851         * Returns the absolute date of Jewish date. ND+ER
852         * 
853         * @param year
854         *            the Jewish year. The year can't be negative
855         * @param month
856         *            the Jewish month starting with Nisan. Nisan expects a value of 1 etc till Adar with a value of 12. For
857         *            a leap year, 13 will be the expected value for Adar II. Use the constants {@link JewishDate#NISSAN}
858         *            etc.
859         * @param dayOfMonth
860         *            the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only
861         *            has 29 days, the day will be set as 29.
862         * @return the absolute date of the Jewish date.
863         */
864        private static int jewishDateToAbsDate(int year, int month, int dayOfMonth) {
865                int elapsed = getDaysSinceStartOfJewishYear(year, month, dayOfMonth);
866                // add elapsed days this year + Days in prior years + Days elapsed before absolute year 1
867                return elapsed + getJewishCalendarElapsedDays(year) + JEWISH_EPOCH;
868        }
869
870        /**
871         * Returns the molad for a given year and month. Returns a JewishDate {@link Object} set to the date of the molad
872         * with the {@link #getMoladHours() hours}, {@link #getMoladMinutes() minutes} and {@link #getMoladChalakim()
873         * chalakim} set. In the current implementation, it sets the molad time based on a midnight date rollover. This
874         * means that Rosh Chodesh Adar II, 5771 with a molad of 7 chalakim past midnight on Shabbos 29 Adar I / March 5,
875         * 2011 12:00 AM and 7 chalakim, will have the following values: hours: 0, minutes: 0, Chalakim: 7.
876         * 
877         * @return a JewishDate {@link Object} set to the date of the molad with the {@link #getMoladHours() hours},
878         *         {@link #getMoladMinutes() minutes} and {@link #getMoladChalakim() chalakim} set.
879         */
880        public JewishDate getMolad() {
881                JewishDate moladDate = new JewishDate(getChalakimSinceMoladTohu());
882                if (moladDate.getMoladHours() >= 6) {
883                        moladDate.forward(Calendar.DATE, 1);
884                }
885                moladDate.setMoladHours((moladDate.getMoladHours() + 18) % 24);
886                return moladDate;
887        }
888
889        /**
890         * Returns the number of days from the Jewish epoch from the number of chalakim from the epoch passed in.
891         * 
892         * @param chalakim
893         *            the number of chalakim since the beginning of Sunday prior to BaHaRaD
894         * @return the number of days from the Jewish epoch
895         */
896        private static int moladToAbsDate(long chalakim) {
897                return (int) (chalakim / CHALAKIM_PER_DAY) + JEWISH_EPOCH;
898        }
899
900        /**
901         * Constructor that creates a JewishDate based on a molad passed in. The molad would be the number of chalakim/parts
902         * starting at the beginning of Sunday prior to the molad Tohu BeHaRaD (Be = Monday, Ha= 5 hours and Rad =204
903         * chalakim/parts) - prior to the start of the Jewish calendar. BeHaRaD is 23:11:20 on Sunday night(5 hours 204/1080
904         * chalakim after sunset on Sunday evening).
905         * 
906         * @param molad the number of chalakim since the beginning of Sunday prior to BaHaRaD
907         */
908        public JewishDate(long molad) {
909                absDateToDate(moladToAbsDate(molad));
910                // long chalakimSince = getChalakimSinceMoladTohu(year, TISHREI);// tishrei
911                int conjunctionDay = (int) (molad / (long) CHALAKIM_PER_DAY);
912                int conjunctionParts = (int) (molad - conjunctionDay * (long) CHALAKIM_PER_DAY);
913                setMoladTime(conjunctionParts);
914        }
915
916        /**
917         * Sets the molad time (hours minutes and chalakim) based on the number of chalakim since the start of the day.
918         * 
919         * @param chalakim
920         *            the number of chalakim since the start of the day.
921         */
922        private void setMoladTime(int chalakim) {
923                int adjustedChalakim = chalakim;
924                setMoladHours(adjustedChalakim / CHALAKIM_PER_HOUR);
925                adjustedChalakim = adjustedChalakim - (getMoladHours() * CHALAKIM_PER_HOUR);
926                setMoladMinutes(adjustedChalakim / CHALAKIM_PER_MINUTE);
927                setMoladChalakim(adjustedChalakim - moladMinutes * CHALAKIM_PER_MINUTE);
928        }
929
930        /**
931         * returns the number of days from Rosh Hashana of the date passed in, to the full date passed in.
932         * 
933         * @param year
934         *            the Jewish year
935         * @param month
936         *            the Jewish month
937         * @param dayOfMonth
938         *            the day in the Jewish month
939         * @return the number of days
940         */
941        private static int getDaysSinceStartOfJewishYear(int year, int month, int dayOfMonth) {
942                int elapsedDays = dayOfMonth;
943                // Before Tishrei (from Nissan to Tishrei), add days in prior months
944                if (month < TISHREI) {
945                        // this year before and after Nisan.
946                        for (int m = TISHREI; m <= getLastMonthOfJewishYear(year); m++) {
947                                elapsedDays += getDaysInJewishMonth(m, year);
948                        }
949                        for (int m = NISSAN; m < month; m++) {
950                                elapsedDays += getDaysInJewishMonth(m, year);
951                        }
952                } else { // Add days in prior months this year
953                        for (int m = TISHREI; m < month; m++) {
954                                elapsedDays += getDaysInJewishMonth(m, year);
955                        }
956                }
957                return elapsedDays;
958        }
959
960        /**
961         * returns the number of days from Rosh Hashana of the date passed in, to the full date passed in.
962         * 
963         * @return the number of days
964         */
965        public int getDaysSinceStartOfJewishYear() {
966                return getDaysSinceStartOfJewishYear(getJewishYear(), getJewishMonth(), getJewishDayOfMonth());
967        }
968
969        /**
970         * Creates a Jewish date based on a Jewish year, month and day of month.
971         * 
972         * @param jewishYear
973         *            the Jewish year
974         * @param jewishMonth
975         *            the Jewish month. The method expects a 1 for Nissan ... 12 for Adar and 13 for Adar II. Use the
976         *            constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar II) to avoid any
977         *            confusion.
978         * @param jewishDayOfMonth
979         *            the Jewish day of month. If 30 is passed in for a month with only 29 days (for example {@link #IYAR},
980         *            or {@link #KISLEV} in a year that {@link #isKislevShort()}), the 29th (last valid date of the month)
981         *            will be set
982         * @throws IllegalArgumentException
983         *             if the day of month is &lt; 1 or &gt; 30, or a year of &lt; 0 is passed in.
984         */
985        public JewishDate(int jewishYear, int jewishMonth, int jewishDayOfMonth) {
986                setJewishDate(jewishYear, jewishMonth, jewishDayOfMonth);
987        }
988
989        /**
990         * Default constructor will set a default date to the current system date.
991         */
992        public JewishDate() {
993                resetDate();
994        }
995
996        /**
997         * A constructor that initializes the date to the {@link java.util.Date Date} paremeter.
998         * 
999         * @param date
1000         *            the <code>Date</code> to set the calendar to
1001         * @throws IllegalArgumentException
1002         *             if the date would fall prior to the January 1, 1 AD
1003         */
1004        public JewishDate(Date date) {
1005                setDate(date);
1006        }
1007
1008        /**
1009         * A constructor that initializes the date to the {@link java.util.Calendar Calendar} paremeter.
1010         * 
1011         * @param calendar
1012         *            the <code>Calendar</code> to set the calendar to
1013         * @throws IllegalArgumentException
1014         *             if the {@link Calendar#ERA} is {@link GregorianCalendar#BC}
1015         */
1016        public JewishDate(Calendar calendar) {
1017                setDate(calendar);
1018        }
1019
1020        /**
1021         * A constructor that initializes the date to the {@link java.time.LocalDate LocalDate} paremeter.
1022         *
1023         * @param localDate
1024         *            the <code>LocalDate</code> to set the calendar to
1025         * @throws IllegalArgumentException
1026         *            if the {@link Calendar#ERA} is {@link GregorianCalendar#BC}
1027         */
1028        public JewishDate(LocalDate localDate) {
1029                setDate(localDate);
1030        }
1031
1032        /**
1033         * Sets the date based on a {@link java.util.Calendar Calendar} object. Modifies the Jewish date as well.
1034         * 
1035         * @param calendar
1036         *            the <code>Calendar</code> to set the calendar to
1037         * @throws IllegalArgumentException
1038         *             if the {@link Calendar#ERA} is {@link GregorianCalendar#BC}
1039         */
1040        public void setDate(Calendar calendar) {
1041                if (calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
1042                        throw new IllegalArgumentException("Calendars with a BC era are not supported. The year "
1043                                        + calendar.get(Calendar.YEAR) + " BC is invalid.");
1044                }
1045                gregorianMonth = calendar.get(Calendar.MONTH) + 1;
1046                gregorianDayOfMonth = calendar.get(Calendar.DATE);
1047                gregorianYear = calendar.get(Calendar.YEAR);
1048                gregorianAbsDate = gregorianDateToAbsDate(gregorianYear, gregorianMonth, gregorianDayOfMonth); // init the date
1049                absDateToJewishDate();
1050
1051                dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // set day of week
1052        }
1053
1054        /**
1055         * Sets the date based on a {@link java.util.Date Date} object. Modifies the Jewish date as well.
1056         * 
1057         * @param date
1058         *            the <code>Date</code> to set the calendar to
1059         * @throws IllegalArgumentException
1060         *             if the date would fall prior to the year 1 AD
1061         */
1062        public void setDate(Date date) {
1063                Calendar cal = Calendar.getInstance();
1064                cal.setTime(date);
1065                setDate(cal);
1066        }
1067
1068        /**
1069         * Sets the date based on a {@link java.time.LocalDate LocalDate} object. Modifies the Jewish date as well.
1070         *
1071         * @param localDate
1072         *            the <code>LocalDate</code> to set the calendar to
1073         * @throws IllegalArgumentException
1074         *             if the date would fall prior to the year 1 AD
1075         */
1076        public void setDate(LocalDate localDate) {
1077                Calendar cal = Calendar.getInstance();
1078                cal.set(localDate.getYear(), localDate.getMonthValue() - 1, localDate.getDayOfMonth());
1079                setDate(cal);
1080        }
1081
1082        /**
1083         * Sets the Gregorian Date, and updates the Jewish date accordingly. Like the Java Calendar A value of 0 is expected
1084         * for January.
1085         * 
1086         * @param year
1087         *            the Gregorian year
1088         * @param month
1089         *            the Gregorian month. Like the Java Calendar, this class expects 0 for January
1090         * @param dayOfMonth
1091         *            the Gregorian day of month. If this is &gt; the number of days in the month/year, the last valid date of
1092         *            the month will be set
1093         * @throws IllegalArgumentException
1094         *             if a year of &lt; 1, a month &lt; 0 or &gt; 11 or a day of month &lt; 1 is passed in
1095         */
1096        public void setGregorianDate(int year, int month, int dayOfMonth) {
1097                validateGregorianDate(year, month, dayOfMonth);
1098                setInternalGregorianDate(year, month + 1, dayOfMonth);
1099        }
1100
1101        /**
1102         * Sets the hidden internal representation of the Gregorian date , and updates the Jewish date accordingly. While
1103         * public getters and setters have 0 based months matching the Java Calendar classes, This class internally
1104         * represents the Gregorian month starting at 1. When this is called it will not adjust the month to match the Java
1105         * Calendar classes.
1106         * 
1107         * @param year the year
1108         * @param month the month
1109         * @param dayOfMonth the day of month
1110         */
1111        private void setInternalGregorianDate(int year, int month, int dayOfMonth) {
1112                // make sure date is a valid date for the given month, if not, set to last day of month
1113                if (dayOfMonth > getLastDayOfGregorianMonth(month, year)) {
1114                        dayOfMonth = getLastDayOfGregorianMonth(month, year);
1115                }
1116                // init month, date, year
1117                gregorianMonth = month;
1118                gregorianDayOfMonth = dayOfMonth;
1119                gregorianYear = year;
1120
1121                gregorianAbsDate = gregorianDateToAbsDate(gregorianYear, gregorianMonth, gregorianDayOfMonth); // init date
1122                absDateToJewishDate();
1123
1124                dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // set day of week
1125        }
1126
1127        /**
1128         * Sets the Jewish Date and updates the Gregorian date accordingly.
1129         * 
1130         * @param year
1131         *            the Jewish year. The year can't be negative
1132         * @param month
1133         *            the Jewish month starting with Nisan. A value of 1 is expected for Nissan ... 12 for Adar and 13 for
1134         *            Adar II. Use the constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar
1135         *            II) to avoid any confusion.
1136         * @param dayOfMonth
1137         *            the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only
1138         *            has 29 days, the day will be set as 29.
1139         * @throws IllegalArgumentException
1140         *             if a A Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month &lt; 1 or &gt; 12 (or 13 on a
1141         *             leap year) or the day of month is &lt; 1 or &gt; 30 is passed in
1142         */
1143        public void setJewishDate(int year, int month, int dayOfMonth) {
1144                setJewishDate(year, month, dayOfMonth, 0, 0, 0);
1145        }
1146
1147        /**
1148         * Sets the Jewish Date and updates the Gregorian date accordingly.
1149         * 
1150         * @param year
1151         *            the Jewish year. The year can't be negative
1152         * @param month
1153         *            the Jewish month starting with Nisan. A value of 1 is expected for Nissan ... 12 for Adar and 13 for
1154         *            Adar II. Use the constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar
1155         *            II) to avoid any confusion.
1156         * @param dayOfMonth
1157         *            the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only
1158         *            has 29 days, the day will be set as 29.
1159         * 
1160         * @param hours
1161         *            the hour of the day. Used for Molad calculations
1162         * @param minutes
1163         *            the minutes. Used for Molad calculations
1164         * @param chalakim
1165         *            the chalakim/parts. Used for Molad calculations. The chalakim should not exceed 17. Minutes should be
1166         *            used for larger numbers.
1167         * 
1168         * @throws IllegalArgumentException
1169         *             if a A Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month &lt; 1 or &gt; 12 (or 13 on a
1170         *             leap year), the day of month is &lt; 1 or &gt; 30, an hour &lt; 0 or &gt; 23, a minute &lt; 0 &gt; 59 or chalakim &lt; 0 &gt;
1171         *             17. For larger a larger number of chalakim such as 793 (TaShTzaG) break the chalakim into minutes (18
1172         *             chalakim per minutes, so it would be 44 minutes and 1 chelek in the case of 793 (TaShTzaG).
1173         */
1174        public void setJewishDate(int year, int month, int dayOfMonth, int hours, int minutes, int chalakim) {
1175                validateJewishDate(year, month, dayOfMonth, hours, minutes, chalakim);
1176
1177                // if 30 is passed for a month that only has 29 days (for example by rolling the month from a month that had 30
1178                // days to a month that only has 29) set the date to 29th
1179                if (dayOfMonth > getDaysInJewishMonth(month, year)) {
1180                        dayOfMonth = getDaysInJewishMonth(month, year);
1181                }
1182
1183                jewishMonth = month;
1184                jewishDay = dayOfMonth;
1185                jewishYear = year;
1186                moladHours = hours;
1187                moladMinutes = minutes;
1188                moladChalakim = chalakim;
1189
1190                gregorianAbsDate = jewishDateToAbsDate(jewishYear, jewishMonth, jewishDay); // reset Gregorian date
1191                absDateToDate(gregorianAbsDate);
1192
1193                dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // reset day of week
1194        }
1195
1196        /**
1197         * Returns this object's date as a {@link java.util.Calendar} object.
1198         * 
1199         * @return The {@link java.util.Calendar}
1200         */
1201        public Calendar getGregorianCalendar() {
1202                Calendar calendar = Calendar.getInstance();
1203                calendar.set(getGregorianYear(), getGregorianMonth(), getGregorianDayOfMonth());
1204                return calendar;
1205        }
1206
1207        /**
1208         * Returns this object's date as a {@link java.time.LocalDate} object.
1209         *
1210         * @return The {@link java.time.LocalDate}
1211         */
1212        public LocalDate getLocalDate() {
1213                return LocalDate.of(getGregorianYear(), getGregorianMonth() + 1, getGregorianDayOfMonth());
1214        }
1215
1216        /**
1217         * Resets this date to the current system date.
1218         */
1219        public void resetDate() {
1220                Calendar calendar = Calendar.getInstance();
1221                setDate(calendar);
1222        }
1223
1224        /**
1225         * Returns a string containing the Jewish date in the form, "day Month, year" e.g. "21 Shevat, 5729". For more
1226         * complex formatting, use the formatter classes.
1227         * 
1228         * @return the Jewish date in the form "day Month, year" e.g. "21 Shevat, 5729"
1229         * @see HebrewDateFormatter#format(JewishDate)
1230         */
1231        public String toString() {
1232                return new HebrewDateFormatter().format(this);
1233        }
1234
1235        /**
1236         * Rolls the date, month or year forward by the amount passed in. It modifies both the Gregorian and Jewish dates accordingly.
1237         * If manipulation beyond the fields supported here is required, use the {@link Calendar} class {@link Calendar#add(int, int)}
1238         * or {@link Calendar#roll(int, int)} methods in the following manner.
1239         * 
1240         * <pre>
1241         * <code>
1242         *      Calendar cal = jewishDate.getTime(); // get a java.util.Calendar representation of the JewishDate
1243         *      cal.add(Calendar.MONTH, 3); // add 3 Gregorian months
1244         *      jewishDate.setDate(cal); // set the updated calendar back to this class
1245         * </code>
1246         * </pre>
1247         * 
1248         * @param field the calendar field to be forwarded. The must be {@link Calendar#DATE}, {@link Calendar#MONTH} or {@link Calendar#YEAR}
1249         * @param amount the positive amount to move forward
1250         * @throws IllegalArgumentException if the field is anything besides {@link Calendar#DATE}, {@link Calendar#MONTH} or {@link Calendar#YEAR}
1251         * or if the amount is less than 1
1252         * 
1253         * @see #back()
1254         * @see Calendar#add(int, int)
1255         * @see Calendar#roll(int, int)
1256         */
1257        public void forward(int field, int amount) {
1258                if (field != Calendar.DATE && field != Calendar.MONTH && field != Calendar.YEAR) {
1259                        throw new IllegalArgumentException("Unsupported field was passed to Forward. Only Calendar.DATE, Calendar.MONTH or Calendar.YEAR are supported.");
1260                }
1261                if (amount < 1) {
1262                        throw new IllegalArgumentException("JewishDate.forward() does not support amounts less than 1. See JewishDate.back()");
1263                }
1264                if (field == Calendar.DATE) {
1265                        // Change Gregorian date
1266                        for (int i = 0; i < amount; i++) {
1267                                if (gregorianDayOfMonth == getLastDayOfGregorianMonth(gregorianMonth, gregorianYear)) {
1268                                        gregorianDayOfMonth = 1;
1269                                        // if last day of year
1270                                        if (gregorianMonth == 12) {
1271                                                gregorianYear++;
1272                                                gregorianMonth = 1;
1273                                        } else {
1274                                                gregorianMonth++;
1275                                        }
1276                                } else { // if not last day of month
1277                                        gregorianDayOfMonth++;
1278                                }
1279                
1280                                // Change the Jewish Date
1281                                if (jewishDay == getDaysInJewishMonth()) {
1282                                        // if it last day of elul (i.e. last day of Jewish year)
1283                                        if (jewishMonth == ELUL) {
1284                                                jewishYear++;
1285                                                jewishMonth++;
1286                                                jewishDay = 1;
1287                                        } else if (jewishMonth == getLastMonthOfJewishYear(jewishYear)) {
1288                                                // if it is the last day of Adar, or Adar II as case may be
1289                                                jewishMonth = NISSAN;
1290                                                jewishDay = 1;
1291                                        } else {
1292                                                jewishMonth++;
1293                                                jewishDay = 1;
1294                                        }
1295                                } else { // if not last date of month
1296                                        jewishDay++;
1297                                }
1298                
1299                                if (dayOfWeek == 7) { // if last day of week, loop back to Sunday
1300                                        dayOfWeek = 1;
1301                                } else {
1302                                        dayOfWeek++;
1303                                }
1304                
1305                                gregorianAbsDate++; // increment the absolute date
1306                        }
1307                } else if (field == Calendar.MONTH) {
1308                        forwardJewishMonth(amount);
1309                } else if (field == Calendar.YEAR) {
1310                        setJewishYear(getJewishYear() + amount);
1311                }
1312        }
1313        
1314        /**
1315         * Forward the Jewish date by the number of months passed in.
1316         * FIXME: Deal with forwarding a date such as 30 Nisan by a month. 30 Iyar does not exist. This should be dealt with similar to 
1317         * the way that the Java Calendar behaves (not that simple since there is a difference between add() or roll().
1318         * 
1319         * @throws IllegalArgumentException if the amount is less than 1
1320         * @param amount the number of months to roll the month forward
1321         */
1322        private void forwardJewishMonth(int amount) {
1323                if (amount < 1) {
1324                        throw new IllegalArgumentException("the amount of months to forward has to be greater than zero.");
1325                }
1326                for (int i = 0; i < amount; i++) {
1327                        if(getJewishMonth() == ELUL) {
1328                                setJewishMonth(TISHREI);
1329                                setJewishYear(getJewishYear() + 1);
1330                        } else if ((! isJewishLeapYear() && getJewishMonth() == ADAR)
1331                                                || (isJewishLeapYear() && getJewishMonth() == ADAR_II)){
1332                                setJewishMonth(NISSAN);
1333                        } else {
1334                                setJewishMonth(getJewishMonth() + 1);
1335                        }
1336                }
1337        }
1338
1339        /**
1340         * Rolls the date back by 1 day. It modifies both the Gregorian and Jewish dates accordingly. The API does not
1341         * currently offer the ability to forward more than one day at a time, or to forward by month or year. If such
1342         * manipulation is required use the {@link Calendar} class {@link Calendar#add(int, int)} or
1343         * {@link Calendar#roll(int, int)} methods in the following manner.
1344         * 
1345         * <pre>
1346         * <code>
1347         *      Calendar cal = jewishDate.getTime(); // get a java.util.Calendar representation of the JewishDate
1348         *      cal.add(Calendar.MONTH, -3); // subtract 3 Gregorian months
1349         *      jewishDate.setDate(cal); // set the updated calendar back to this class
1350         * </code>
1351         * </pre>
1352         * 
1353         * @see #back()
1354         * @see Calendar#add(int, int)
1355         * @see Calendar#roll(int, int)
1356         */
1357        public void back() {
1358                // Change Gregorian date
1359                if (gregorianDayOfMonth == 1) { // if first day of month
1360                        if (gregorianMonth == 1) { // if first day of year
1361                                gregorianMonth = 12;
1362                                gregorianYear--;
1363                        } else {
1364                                gregorianMonth--;
1365                        }
1366                        // change to last day of previous month
1367                        gregorianDayOfMonth = getLastDayOfGregorianMonth(gregorianMonth, gregorianYear);
1368                } else {
1369                        gregorianDayOfMonth--;
1370                }
1371                // change Jewish date
1372                if (jewishDay == 1) { // if first day of the Jewish month
1373                        if (jewishMonth == NISSAN) {
1374                                jewishMonth = getLastMonthOfJewishYear(jewishYear);
1375                        } else if (jewishMonth == TISHREI) { // if Rosh Hashana
1376                                jewishYear--;
1377                                jewishMonth--;
1378                        } else {
1379                                jewishMonth--;
1380                        }
1381                        jewishDay = getDaysInJewishMonth();
1382                } else {
1383                        jewishDay--;
1384                }
1385
1386                if (dayOfWeek == 1) { // if first day of week, loop back to Saturday
1387                        dayOfWeek = 7;
1388                } else {
1389                        dayOfWeek--;
1390                }
1391                gregorianAbsDate--; // change the absolute date
1392        }
1393
1394        /**
1395         * Indicates whether some other object is "equal to" this one.
1396         * @see Object#equals(Object)
1397         */
1398        public boolean equals(Object object) {
1399                if (this == object) {
1400                        return true;
1401                }
1402                if (!(object instanceof JewishDate)) {
1403                        return false;
1404                }
1405                JewishDate jewishDate = (JewishDate) object;
1406                return gregorianAbsDate == jewishDate.getAbsDate();
1407        }
1408
1409        /**
1410         * Compares two dates as per the compareTo() method in the Comparable interface. Returns a value less than 0 if this
1411         * date is "less than" (before) the date, greater than 0 if this date is "greater than" (after) the date, or 0 if
1412         * they are equal.
1413         */
1414        public int compareTo(JewishDate jewishDate) {
1415                return Integer.compare(gregorianAbsDate, jewishDate.getAbsDate());
1416        }
1417
1418        /**
1419         * Returns the Gregorian month (between 0-11).
1420         * 
1421         * @return the Gregorian month (between 0-11). Like the java.util.Calendar, months are 0 based.
1422         */
1423        public int getGregorianMonth() {
1424                return gregorianMonth - 1;
1425        }
1426
1427        /**
1428         * Returns the Gregorian day of the month.
1429         * 
1430         * @return the Gregorian day of the mont
1431         */
1432        public int getGregorianDayOfMonth() {
1433                return gregorianDayOfMonth;
1434        }
1435
1436        /**
1437         * Returns the Gregotian year.
1438         * 
1439         * @return the Gregorian year
1440         */
1441        public int getGregorianYear() {
1442                return gregorianYear;
1443        }
1444
1445        /**
1446         * Returns the Jewish month 1-12 (or 13 years in a leap year). The month count starts with 1 for Nisan and goes to
1447         * 13 for Adar II
1448         * 
1449         * @return the Jewish month from 1 to 12 (or 13 years in a leap year). The month count starts with 1 for Nisan and
1450         *         goes to 13 for Adar II
1451         */
1452        public int getJewishMonth() {
1453                return jewishMonth;
1454        }
1455
1456        /**
1457         * Returns the Jewish day of month.
1458         * 
1459         * @return the Jewish day of the month
1460         */
1461        public int getJewishDayOfMonth() {
1462                return jewishDay;
1463        }
1464
1465        /**
1466         * Returns the Jewish year.
1467         * 
1468         * @return the Jewish year
1469         */
1470        public int getJewishYear() {
1471                return jewishYear;
1472        }
1473
1474        /**
1475         * Returns the day of the week as a number between 1-7.
1476         * 
1477         * @return the day of the week as a number between 1-7.
1478         */
1479        public int getDayOfWeek() {
1480                return dayOfWeek;
1481        }
1482
1483        /**
1484         * Sets the Gregorian month.
1485         * 
1486         * @param month
1487         *            the Gregorian month
1488         * 
1489         * @throws IllegalArgumentException
1490         *             if a month &lt; 0 or &gt; 11 is passed in
1491         */
1492        public void setGregorianMonth(int month) {
1493                validateGregorianMonth(month);
1494                setInternalGregorianDate(gregorianYear, month + 1, gregorianDayOfMonth);
1495        }
1496
1497        /**
1498         * sets the Gregorian year.
1499         * 
1500         * @param year
1501         *            the Gregorian year.
1502         * @throws IllegalArgumentException
1503         *             if a year of &lt; 1 is passed in
1504         */
1505        public void setGregorianYear(int year) {
1506                validateGregorianYear(year);
1507                setInternalGregorianDate(year, gregorianMonth, gregorianDayOfMonth);
1508        }
1509
1510        /**
1511         * sets the Gregorian Day of month.
1512         * 
1513         * @param dayOfMonth
1514         *            the Gregorian Day of month.
1515         * @throws IllegalArgumentException
1516         *             if the day of month of &lt; 1 is passed in
1517         */
1518        public void setGregorianDayOfMonth(int dayOfMonth) {
1519                validateGregorianDayOfMonth(dayOfMonth);
1520                setInternalGregorianDate(gregorianYear, gregorianMonth, dayOfMonth);
1521        }
1522
1523        /**
1524         * sets the Jewish month.
1525         * 
1526         * @param month
1527         *            the Jewish month from 1 to 12 (or 13 years in a leap year). The month count starts with 1 for Nisan
1528         *            and goes to 13 for Adar II
1529         * @throws IllegalArgumentException
1530         *             if a month &lt; 1 or &gt; 12 (or 13 on a leap year) is passed in
1531         */
1532        public void setJewishMonth(int month) {
1533                setJewishDate(jewishYear, month, jewishDay);
1534        }
1535
1536        /**
1537         * sets the Jewish year.
1538         * 
1539         * @param year
1540         *            the Jewish year
1541         * @throws IllegalArgumentException
1542         *             if a year of &lt; 3761 is passed in. The same will happen if the year is 3761 and the month and day
1543         *             previously set are &lt; 18 Teves (preior to Jan 1, 1 AD)
1544         */
1545        public void setJewishYear(int year) {
1546                setJewishDate(year, jewishMonth, jewishDay);
1547        }
1548
1549        /**
1550         * sets the Jewish day of month.
1551         * 
1552         * @param dayOfMonth
1553         *            the Jewish day of month
1554         * @throws IllegalArgumentException
1555         *             if the day of month is &lt; 1 or &gt; 30 is passed in
1556         */
1557        public void setJewishDayOfMonth(int dayOfMonth) {
1558                setJewishDate(jewishYear, jewishMonth, dayOfMonth);
1559        }
1560
1561        /**
1562         * A method that creates a <a href="http://en.wikipedia.org/wiki/Object_copy#Deep_copy">deep copy</a> of the object.
1563         * 
1564         * @see Object#clone()
1565         */
1566        public Object clone() {
1567                JewishDate clone = null;
1568                try {
1569                        clone = (JewishDate) super.clone();
1570                } catch (CloneNotSupportedException cnse) {
1571                        // Required by the compiler. Should never be reached since we implement clone()
1572                }
1573                clone.setInternalGregorianDate(gregorianYear, gregorianMonth, gregorianDayOfMonth);
1574                return clone;
1575        }
1576
1577        /**
1578         * Overrides {@link Object#hashCode()}.
1579         * @see Object#hashCode()
1580         */
1581        public int hashCode() {
1582                int result = 17;
1583                result = 37 * result + getClass().hashCode(); // needed or this and subclasses will return identical hash
1584                result += 37 * result + gregorianAbsDate;
1585                return result;
1586        }
1587}