001/*
002 * Zmanim Java API
003 * Copyright (C) 2011 - 2024 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 - 2024
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 of the Gregorian calendar
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 <em>molad BaHaRaD</em>. Calculated as 1 day, 5 hours and 204 <em>chalakim</em> =
162         * (24 + 5) * 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 chalakim</em>.*/
201        private int moladChalakim;
202
203        /**
204         * Returns the <em>molad</em> 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 <em>molad</em> 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 <em>molad</em> hours.
219         * 
220         * @param moladHours
221         *            the <em>molad</em> 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 <em>molad</em> 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 <em>molad</em> 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 <em>molad</em> minutes. The expectation is that the traditional minute-less <em>chalakim</em> will be broken out to
247         * minutes and {@link #setMoladChalakim(int) <em>chalakim</em> / parts} , so 793 (TaShTZaG) parts would have the minutes set to
248         * 44 and <em>chalakim</em> 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 <em>molad</em> chalakim/parts. The expectation is that the traditional minute-less <em>chalakim</em> will be broken
264         * out to {@link #setMoladMinutes(int) minutes} and chalakim, so 793 (TaShTZaG) parts would have the minutes set to 44 and
265         * <em>chalakim</em> to 1.
266         * 
267         * @param moladChalakim
268         *            the <em>molad chalakim</em> / 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 <em>molad chalakim</em> / 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 <em>molad chalakim</em> / 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 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 of 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 of 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 <em>molad Tohu BaHaRaD</em> (Be = Monday, <em>Ha</em> = 5
457         *         hours and <em>RaD</em> = 204 <em>chalakim</em> / parts) prior to the start of the Jewish calendar, to
458         *         the mean conjunction of Tishri of the Jewish year. BeHaRaD is 23:11:20 on Sunday night(5 hours 204/1080
459         *         <em>chalakim</em> after sunset on Sunday 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        /**
470         * Adds the 4 dechiyos for <em>molad</em> Tishrei. These are:
471         * <ol>
472         * <li><em>Lo ADU Rosh</em> - Rosh Hashana can't fall on a Sunday, Wednesday or Friday. If the <em>molad</em> fell on one
473         * of these days, Rosh Hashana is delayed to the following day.</li>
474         * <li><em>Molad Zaken</em> - If the <em>molad</em> of Tishrei falls after 12 noon, Rosh Hashana is delayed to the following
475         * day. If the following day is <em>ADU</em>, it will be delayed an additional day.</li>
476         * <li><em>GaTRaD</em> - If on a non leap year the <em>molad</em> of Tishrei falls on a Tuesday (Ga) on or after 9 hours
477         * (<em>T</em>) and (<em>RaD</em> 204 <em>chalakim</em> it is delayed till Thursday (one day delay, plus one day for
478         * <em>Lo ADU Rosh</em>)</li>
479         * <li><em>BeTuTaKPaT</em> - if the year following a leap year falls on a Monday (<em>Be</em>) on or after 15 hours
480         * (<em>Tu</em>) and 589 <em>chalakim</em> (<em>TaKPaT</em>) it is delayed till Tuesday</li>
481         * </ol>
482         * 
483         * @param year the year
484         * @param moladDay the <em>molad</em> day
485         * @param moladParts the <em>molad</em> parts
486         * @return the number of elapsed days in the JewishCalendar adjusted for the 4 dechiyos.
487         */
488        private static int addDechiyos(int year, int moladDay, int moladParts) {
489                int roshHashanaDay = moladDay; // if no dechiyos
490                // delay Rosh Hashana for the dechiyos of the Molad - new moon 1 - Molad Zaken, 2- GaTRaD 3- BeTuTaKPaT
491                if ((moladParts >= 19440) // Dechiya of Molad Zaken - molad is >= midday (18 hours * 1080 chalakim)
492                                || (((moladDay % 7) == 2) // start Dechiya of GaTRaD - Ga = is a Tuesday
493                                                && (moladParts >= 9924) // TRaD = 9 hours, 204 parts or later (9 * 1080 + 204)
494                                && !isJewishLeapYear(year)) // of a non-leap year - end Dechiya of GaTRaD
495                                || (((moladDay % 7) == 1) // start Dechiya of BeTuTaKPaT - Be = is on a Monday
496                                                && (moladParts >= 16789) // TUTaKPaT part of BeTuTaKPaT = 15 hours, 589 parts or later (15 * 1080 + 589)
497                                && (isJewishLeapYear(year - 1)))) { // in a year following a leap year - end Dechiya of BeTuTaKPaT
498                        roshHashanaDay += 1; // Then postpone Rosh HaShanah one day
499                }
500                // start 4th Dechiya - Lo ADU Rosh - Rosh Hashana can't occur on A- sunday, D- Wednesday, U - Friday
501                if (((roshHashanaDay % 7) == 0)// If Rosh HaShanah would occur on Sunday,
502                                || ((roshHashanaDay % 7) == 3) // or Wednesday,
503                                || ((roshHashanaDay % 7) == 5)) { // or Friday - end 4th Dechiya - Lo ADU Rosh
504                        roshHashanaDay = roshHashanaDay + 1; // Then postpone it one (more) day
505                }
506                return roshHashanaDay;
507        }
508
509        /**
510         * Returns the number of <em>chalakim</em> (parts - 1080 to the hour) from the original hypothetical <em>Molad Tohu</em>
511         * to the year and month passed in.
512         * 
513         * @param year
514         *            the Jewish year
515         * @param month
516         *            the Jewish month the Jewish month, with the month numbers starting from Nissan. Use the JewishDate
517         *            constants such as {@link JewishDate#TISHREI}.
518         * @return the number of <em>chalakim</em> (parts - 1080 to the hour) from the original hypothetical <em>Molad Tohu</em>
519         */
520        private static long getChalakimSinceMoladTohu(int year, int month) {
521                // Jewish lunar month = 29 days, 12 hours and 793 chalakim
522                // chalakim since Molad Tohu BeHaRaD - 1 day, 5 hours and 204 chalakim
523                int monthOfYear = getJewishMonthOfYear(year, month);
524                int monthsElapsed = (235 * ((year - 1) / 19)) // Months in complete 19-year lunar (Metonic) cycles so far
525                                + (12 * ((year - 1) % 19)) // Regular months in this cycle
526                                + ((7 * ((year - 1) % 19) + 1) / 19) // Leap months this cycle
527                                + (monthOfYear - 1); // add elapsed months till the start of the molad of the month
528                // return chalakim prior to BeHaRaD + number of chalakim since
529                return CHALAKIM_MOLAD_TOHU + (CHALAKIM_PER_MONTH * monthsElapsed);
530        }
531
532        /**
533         * Returns the number of <em>chalakim</em> (parts - 1080 to the hour) from the original hypothetical <em>Molad Tohu</em>
534         * to the Jewish year and month that this Object is set to.
535         * 
536         * @return the number of <em>chalakim</em> (parts - 1080 to the hour) from the original hypothetical <em>Molad Tohu</em> 
537         */
538        public long getChalakimSinceMoladTohu() {
539                return getChalakimSinceMoladTohu(jewishYear, jewishMonth);
540        }
541
542        /**
543         * Converts the {@link JewishDate#NISSAN} based constants used by this class to numeric month starting from
544         * {@link JewishDate#TISHREI}. This is required for <em>molad</em> calculations.
545         * 
546         * @param year
547         *            The Jewish year
548         * @param month
549         *            The Jewish Month
550         * @return the Jewish month of the year starting with Tishrei
551         */
552        private static int getJewishMonthOfYear(int year, int month) {
553                boolean isLeapYear = isJewishLeapYear(year);
554                return (month + (isLeapYear ? 6 : 5)) % (isLeapYear ? 13 : 12) + 1;
555        }
556
557        /**
558         * Validates the components of a Jewish date for validity. It will throw an {@link IllegalArgumentException} if the Jewish
559         * date is earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month &lt; 1 or &gt; 12 (or 13 on a {@link #isJewishLeapYear(int)
560         * 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
561         * <em>chalakim</em> &lt; 0 or &gt; 17. For larger a larger number of <em>chalakim</em> such as 793 (TaShTzaG) break the
562         * <em>chalakim</em> into minutes (18 <em>chalakim</em> per minutes, so it would be 44 minutes and 1 <em>chelek</em> in the
563         * case of 793 / <em>TaShTzaG</em>).
564         * 
565         * @param year
566         *            the Jewish year to validate. It will reject any year &lt;= 3761 (lower than the year 1 Gregorian).
567         * @param month
568         *            the Jewish month to validate. It will reject a month &lt; 1 or &gt; 12 (or 13 on a leap year) .
569         * @param dayOfMonth
570         *            the day of the Jewish month to validate. It will reject any value &lt; 1 or &gt; 30 TODO: check calling
571         *            methods to see if there is any reason that the class can validate that 30 is invalid for some months.
572         * @param hours
573         *            the hours (for <em>molad</em> calculations). It will reject an hour &lt; 0 or &gt; 23
574         * @param minutes
575         *            the minutes (for <em>molad</em> calculations). It will reject a minute &lt; 0 or &gt; 59
576         * @param chalakim
577         *            the <em>chalakim</em> / parts (for <em>molad</em> calculations). It will reject a <em>chalakim</em> &lt; 0 or &gt;
578         *            17. For larger numbers such as 793 (<em>TaShTzaG</em>) break the <em>chalakim</em> into minutes (18 <em>chalakim</em>
579         *            per minutes, so it would be 44  minutes and 1 <em>chelek</em> in the case of 793 / <em>TaShTzaG</em>)
580         * 
581         * @throws IllegalArgumentException
582         *             if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month &lt; 1 or &gt; 12 (or 13 on a leap year),
583         *             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 <em>chalakim</em>
584         *             &lt; 0 or &gt; 17. For larger a larger number of <em>chalakim</em> such as 793 (<em>TaShTzaG</em>) break the
585         *             <em>chalakim</em> into minutes (18 <em>chalakim</em> per minutes, so it would be 44 minutes and 1 <em>chelek</em>
586         *             in the case of 793 (<em>TaShTzaG</em>).
587         */
588        private static void validateJewishDate(int year, int month, int dayOfMonth, int hours, int minutes, int chalakim) {
589                if (month < NISSAN || month > getLastMonthOfJewishYear(year)) {
590                        throw new IllegalArgumentException("The Jewish month has to be between 1 and 12 (or 13 on a leap year). "
591                                        + month + " is invalid for the year " + year + ".");
592                }
593                if (dayOfMonth < 1 || dayOfMonth > 30) {
594                        throw new IllegalArgumentException("The Jewish day of month can't be < 1 or > 30.  " + dayOfMonth
595                                        + " is invalid.");
596                }
597                // reject dates prior to 18 Teves, 3761 (1/1/1 AD). This restriction can be relaxed if the date coding is
598                // changed/corrected
599                if ((year < 3761) || (year == 3761 && (month >= TISHREI && month < TEVES))
600                                || (year == 3761 && month == TEVES && dayOfMonth < 18)) {
601                        throw new IllegalArgumentException(
602                                        "A Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian) can't be set. " + year + ", " + month
603                                                        + ", " + dayOfMonth + " is invalid.");
604                }
605                if (hours < 0 || hours > 23) {
606                        throw new IllegalArgumentException("Hours < 0 or > 23 can't be set. " + hours + " is invalid.");
607                }
608
609                if (minutes < 0 || minutes > 59) {
610                        throw new IllegalArgumentException("Minutes < 0 or > 59 can't be set. " + minutes + " is invalid.");
611                }
612
613                if (chalakim < 0 || chalakim > 17) {
614                        throw new IllegalArgumentException(
615                                        "Chalakim/parts < 0 or > 17 can't be set. "
616                                                        + chalakim
617                                                        + " is invalid. For larger numbers such as 793 (TaShTzaG) break the <em>chalakim</em> into minutes (18 chalakim per minutes, so it would be 44 minutes and 1 chelek in the case of 793 (TaShTzaG)");
618                }
619        }
620
621        /**
622         * Validates the components of a Gregorian date for validity. It will throw an {@link IllegalArgumentException} if a
623         * year of &lt; 1, a month &lt; 0 or &gt; 11 or a day of month &lt; 1 is passed in.
624         * 
625         * @param year
626         *            the Gregorian year to validate. It will reject any year &lt; 1.
627         * @param month
628         *            the Gregorian month number to validate. It will enforce that the month is between 0 - 11 like a
629         *            {@link GregorianCalendar}, where {@link Calendar#JANUARY} has a value of 0.
630         * @param dayOfMonth
631         *            the day of the Gregorian month to validate. It will reject any value &lt; 1, but will allow values &gt; 31
632         *            since calling methods will simply set it to the maximum for that month. TODO: check calling methods to
633         *            see if there is any reason that the class needs days &gt; the maximum.
634         * @throws IllegalArgumentException
635         *             if a year of &lt; 1, a month &lt; 0 or &gt; 11 or a day of month &lt; 1 is passed in
636         * @see #validateGregorianYear(int)
637         * @see #validateGregorianMonth(int)
638         * @see #validateGregorianDayOfMonth(int)
639         */
640        private static void validateGregorianDate(int year, int month, int dayOfMonth) {
641                validateGregorianMonth(month);
642                validateGregorianDayOfMonth(dayOfMonth);
643                validateGregorianYear(year);
644        }
645
646        /**
647         * Validates a Gregorian month for validity.
648         * 
649         * @param month
650         *            the Gregorian month number to validate. It will enforce that the month is between 0 - 11 like a
651         *            {@link GregorianCalendar}, where {@link Calendar#JANUARY} has a value of 0.
652         */
653        private static void validateGregorianMonth(int month) {
654                if (month > 11 || month < 0) {
655                        throw new IllegalArgumentException("The Gregorian month has to be between 0 - 11. " + month
656                                        + " is invalid.");
657                }
658        }
659
660        /**
661         * Validates a Gregorian day of month for validity.
662         * 
663         * @param dayOfMonth
664         *            the day of the Gregorian month to validate. It will reject any value &lt; 1, but will allow values &gt; 31
665         *            since calling methods will simply set it to the maximum for that month. TODO: check calling methods to
666         *            see if there is any reason that the class needs days &gt; the maximum.
667         */
668        private static void validateGregorianDayOfMonth(int dayOfMonth) {
669                if (dayOfMonth <= 0) {
670                        throw new IllegalArgumentException("The day of month can't be less than 1. " + dayOfMonth + " is invalid.");
671                }
672        }
673
674        /**
675         * Validates a Gregorian year for validity.
676         * 
677         * @param year
678         *            the Gregorian year to validate. It will reject any year &lt; 1.
679         */
680        private static void validateGregorianYear(int year) {
681                if (year < 1) {
682                        throw new IllegalArgumentException("Years < 1 can't be calculated. " + year + " is invalid.");
683                }
684        }
685
686        /**
687         * Returns the number of days for a given Jewish year. ND+ER
688         * 
689         * @param year
690         *            the Jewish year
691         * @return the number of days for a given Jewish year.
692         * @see #isCheshvanLong()
693         * @see #isKislevShort()
694         */
695        public static int getDaysInJewishYear(int year) {
696                return getJewishCalendarElapsedDays(year + 1) - getJewishCalendarElapsedDays(year);
697        }
698
699        /**
700         * Returns the number of days for the current year that the calendar is set to.
701         * 
702         * @return the number of days for the Object's current Jewish year.
703         * @see #isCheshvanLong()
704         * @see #isKislevShort()
705         * @see #isJewishLeapYear()
706         */
707        public int getDaysInJewishYear() {
708                return getDaysInJewishYear(getJewishYear());
709        }
710
711        /**
712         * Returns if Cheshvan is long in a given Jewish year. The method name isLong is done since in a Kesidran (ordered)
713         * year Cheshvan is short. ND+ER
714         * 
715         * @param year
716         *            the year
717         * @return true if Cheshvan is long in Jewish year.
718         * @see #isCheshvanLong()
719         * @see #getCheshvanKislevKviah()
720         */
721        private static boolean isCheshvanLong(int year) {
722                return getDaysInJewishYear(year) % 10 == 5;
723        }
724
725        /**
726         * Returns if Cheshvan is long (30 days VS 29 days) for the current year that the calendar is set to. The method
727         * name isLong is done since in a Kesidran (ordered) year Cheshvan is short.
728         * 
729         * @return true if Cheshvan is long for the current year that the calendar is set to
730         * @see #isCheshvanLong()
731         */
732        public boolean isCheshvanLong() {
733                return isCheshvanLong(getJewishYear());
734        }
735
736        /**
737         * Returns if Kislev is short (29 days VS 30 days) in a given Jewish year. The method name isShort is done since in
738         * a Kesidran (ordered) year Kislev is long. ND+ER
739         * 
740         * @param year
741         *            the Jewish year
742         * @return true if Kislev is short for the given Jewish year.
743         * @see #isKislevShort()
744         * @see #getCheshvanKislevKviah()
745         */
746        private static boolean isKislevShort(int year) {
747                return getDaysInJewishYear(year) % 10 == 3;
748        }
749
750        /**
751         * Returns if the Kislev is short for the year that this class is set to. The method name isShort is done since in a
752         * Kesidran (ordered) year Kislev is long.
753         * 
754         * @return true if Kislev is short for the year that this class is set to
755         */
756        public boolean isKislevShort() {
757                return isKislevShort(getJewishYear());
758        }
759
760        /**
761         * Returns the Cheshvan and Kislev kviah (whether a Jewish year is short, regular or long). It will return
762         * {@link #SHELAIMIM} if both cheshvan and kislev are 30 days, {@link #KESIDRAN} if Cheshvan is 29 days and Kislev
763         * is 30 days and {@link #CHASERIM} if both are 29 days.
764         * 
765         * @return {@link #SHELAIMIM} if both cheshvan and kislev are 30 days, {@link #KESIDRAN} if Cheshvan is 29 days and
766         *         Kislev is 30 days and {@link #CHASERIM} if both are 29 days.
767         * @see #isCheshvanLong()
768         * @see #isKislevShort()
769         */
770        public int getCheshvanKislevKviah() {
771                if (isCheshvanLong() && !isKislevShort()) {
772                        return SHELAIMIM;
773                } else if (!isCheshvanLong() && isKislevShort()) {
774                        return CHASERIM;
775                } else {
776                        return KESIDRAN;
777                }
778        }
779
780        /**
781         * Returns the number of days of a Jewish month for a given month and year.
782         * 
783         * @param month
784         *            the Jewish month
785         * @param year
786         *            the Jewish Year
787         * @return the number of days for a given Jewish month
788         */
789        private static int getDaysInJewishMonth(int month, int year) {
790                if ((month == IYAR) || (month == TAMMUZ) || (month == ELUL) || ((month == CHESHVAN) && !(isCheshvanLong(year)))
791                                || ((month == KISLEV) && isKislevShort(year)) || (month == TEVES)
792                                || ((month == ADAR) && !(isJewishLeapYear(year))) || (month == ADAR_II)) {
793                        return 29;
794                } else {
795                        return 30;
796                }
797        }
798
799        /**
800         * Returns the number of days of the Jewish month that the calendar is currently set to.
801         * 
802         * @return the number of days for the Jewish month that the calendar is currently set to.
803         */
804        public int getDaysInJewishMonth() {
805                return getDaysInJewishMonth(getJewishMonth(), getJewishYear());
806        }
807
808        /**
809         * Computes the Jewish date from the absolute date.
810         */
811        private void absDateToJewishDate() {
812                // Approximation from below
813                jewishYear = (gregorianAbsDate - JEWISH_EPOCH) / 366;
814                // Search forward for year from the approximation
815                while (gregorianAbsDate >= jewishDateToAbsDate(jewishYear + 1, TISHREI, 1)) {
816                        jewishYear++;
817                }
818                // Search forward for month from either Tishri or Nissan.
819                if (gregorianAbsDate < jewishDateToAbsDate(jewishYear, NISSAN, 1)) {
820                        jewishMonth = TISHREI;// Start at Tishri
821                } else {
822                        jewishMonth = NISSAN;// Start at Nissan
823                }
824                while (gregorianAbsDate > jewishDateToAbsDate(jewishYear, jewishMonth, getDaysInJewishMonth())) {
825                        jewishMonth++;
826                }
827                // Calculate the day by subtraction
828                jewishDay = gregorianAbsDate - jewishDateToAbsDate(jewishYear, jewishMonth, 1) + 1;
829        }
830
831        /**
832         * Returns the absolute date of Jewish date. ND+ER
833         * 
834         * @param year
835         *            the Jewish year. The year can't be negative
836         * @param month
837         *            the Jewish month starting with Nissan. Nissan expects a value of 1 etc. until Adar with a value of 12.
838         *            For a leap year, 13 will be the expected value for Adar II. Use the constants {@link JewishDate#NISSAN}
839         *            etc.
840         * @param dayOfMonth
841         *            the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only
842         *            has 29 days, the day will be set as 29.
843         * @return the absolute date of the Jewish date.
844         */
845        private static int jewishDateToAbsDate(int year, int month, int dayOfMonth) {
846                int elapsed = getDaysSinceStartOfJewishYear(year, month, dayOfMonth);
847                // add elapsed days this year + Days in prior years + Days elapsed before absolute year 1
848                return elapsed + getJewishCalendarElapsedDays(year) + JEWISH_EPOCH;
849        }
850
851        /**
852         * Returns the <em>molad</em> for a given year and month. Returns a JewishDate {@link Object} set to the date of the <em>molad</em>
853         * with the {@link #getMoladHours() hours}, {@link #getMoladMinutes() minutes} and {@link #getMoladChalakim()
854         * chalakim} set. In the current implementation, it sets the <em>molad</em> time based on a midnight date rollover. This
855         * means that Rosh Chodesh Adar II, 5771 with a <em>molad</em> of 7 <em>chalakim</em> past midnight on Shabbos 29 Adar I / March 5,
856         * 2011 12:00 AM and 7 chalakim, will have the following values: hours: 0, minutes: 0, Chalakim: 7.
857         * 
858         * @return a JewishDate {@link Object} set to the date of the <em>molad</em> with the {@link #getMoladHours() hours},
859         *         {@link #getMoladMinutes() minutes} and {@link #getMoladChalakim() <em>chalakim</em>} set.
860         */
861        public JewishDate getMolad() {
862                JewishDate moladDate = new JewishDate(getChalakimSinceMoladTohu());
863                if (moladDate.getMoladHours() >= 6) {
864                        moladDate.forward(Calendar.DATE, 1);
865                }
866                moladDate.setMoladHours((moladDate.getMoladHours() + 18) % 24);
867                return moladDate;
868        }
869
870        /**
871         * Returns the number of days from the Jewish epoch from the number of <em>chalakim</em> from the epoch passed in.
872         * 
873         * @param chalakim
874         *            the number of <em>chalakim</em> since the beginning of Sunday prior to BaHaRaD
875         * @return the number of days from the Jewish epoch
876         */
877        private static int moladToAbsDate(long chalakim) {
878                return (int) (chalakim / CHALAKIM_PER_DAY) + JEWISH_EPOCH;
879        }
880
881        /**
882         * Constructor that creates a JewishDate based on a <em>molad</em> passed in. The <em>molad</em> would be the number of
883         * <em>chalakim</em> / parts starting at the beginning of Sunday prior to the <em>Molad Tohu BeHaRaD</em> (<em>Be</em> =
884         * Monday, <em>Ha</em> = 5 hours and <em>RaD</em> = 204 <em>chalakim</em> / parts) - prior to the start of the Jewish
885         * calendar. <em>BeHaRaD</em> is 23:11:20 on Sunday night(5 hours 204/1080 <em>chalakim</em> after sunset on Sunday evening).
886         * 
887         * @param molad the number of <em>chalakim</em> since the beginning of Sunday prior to BaHaRaD
888         */
889        public JewishDate(long molad) {
890                absDateToDate(moladToAbsDate(molad));
891                int conjunctionDay = (int) (molad / (long) CHALAKIM_PER_DAY);
892                int conjunctionParts = (int) (molad - conjunctionDay * (long) CHALAKIM_PER_DAY);
893                setMoladTime(conjunctionParts);
894        }
895
896        /**
897         * Sets the <em>molad</em> time (hours minutes and chalakim) based on the number of <em>chalakim</em> since the start of the day.
898         * 
899         * @param chalakim
900         *            the number of <em>chalakim</em> since the start of the day.
901         */
902        private void setMoladTime(int chalakim) {
903                int adjustedChalakim = chalakim;
904                setMoladHours(adjustedChalakim / CHALAKIM_PER_HOUR);
905                adjustedChalakim = adjustedChalakim - (getMoladHours() * CHALAKIM_PER_HOUR);
906                setMoladMinutes(adjustedChalakim / CHALAKIM_PER_MINUTE);
907                setMoladChalakim(adjustedChalakim - moladMinutes * CHALAKIM_PER_MINUTE);
908        }
909
910        /**
911         * returns the number of days from Rosh Hashana of the date passed in, to the full date passed in.
912         * 
913         * @param year
914         *            the Jewish year
915         * @param month
916         *            the Jewish month
917         * @param dayOfMonth
918         *            the day in the Jewish month
919         * @return the number of days
920         */
921        private static int getDaysSinceStartOfJewishYear(int year, int month, int dayOfMonth) {
922                int elapsedDays = dayOfMonth;
923                // Before Tishrei (from Nissan to Tishrei), add days in prior months
924                if (month < TISHREI) {
925                        // this year before and after Nissan.
926                        for (int m = TISHREI; m <= getLastMonthOfJewishYear(year); m++) {
927                                elapsedDays += getDaysInJewishMonth(m, year);
928                        }
929                        for (int m = NISSAN; m < month; m++) {
930                                elapsedDays += getDaysInJewishMonth(m, year);
931                        }
932                } else { // Add days in prior months this year
933                        for (int m = TISHREI; m < month; m++) {
934                                elapsedDays += getDaysInJewishMonth(m, year);
935                        }
936                }
937                return elapsedDays;
938        }
939
940        /**
941         * returns the number of days from Rosh Hashana of the date passed in, to the full date passed in.
942         * 
943         * @return the number of days
944         */
945        public int getDaysSinceStartOfJewishYear() {
946                return getDaysSinceStartOfJewishYear(getJewishYear(), getJewishMonth(), getJewishDayOfMonth());
947        }
948
949        /**
950         * Creates a Jewish date based on a Jewish year, month and day of month.
951         * 
952         * @param jewishYear
953         *            the Jewish year
954         * @param jewishMonth
955         *            the Jewish month. The method expects a 1 for Nissan ... 12 for Adar and 13 for Adar II. Use the
956         *            constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar II) to avoid any
957         *            confusion.
958         * @param jewishDayOfMonth
959         *            the Jewish day of month. If 30 is passed in for a month with only 29 days (for example {@link #IYAR},
960         *            or {@link #KISLEV} in a year that {@link #isKislevShort()}), the 29th (last valid date of the month)
961         *            will be set
962         * @throws IllegalArgumentException
963         *             if the day of month is &lt; 1 or &gt; 30, or a year of &lt; 0 is passed in.
964         */
965        public JewishDate(int jewishYear, int jewishMonth, int jewishDayOfMonth) {
966                setJewishDate(jewishYear, jewishMonth, jewishDayOfMonth);
967        }
968
969        /**
970         * Default constructor will set a default date to the current system date.
971         */
972        public JewishDate() {
973                resetDate();
974        }
975
976        /**
977         * A constructor that initializes the date to the {@link java.util.Date Date} parameter.
978         * 
979         * @param date
980         *            the <code>Date</code> to set the calendar to
981         * @throws IllegalArgumentException
982         *             if the date would fall prior to the January 1, 1 AD
983         */
984        public JewishDate(Date date) {
985                setDate(date);
986        }
987
988        /**
989         * A constructor that initializes the date to the {@link java.util.Calendar Calendar} parameter.
990         * 
991         * @param calendar
992         *            the <code>Calendar</code> to set the calendar to
993         * @throws IllegalArgumentException
994         *             if the {@link Calendar#ERA} is {@link GregorianCalendar#BC}
995         */
996        public JewishDate(Calendar calendar) {
997                setDate(calendar);
998        }
999
1000        /**
1001         * A constructor that initializes the date to the {@link java.time.LocalDate LocalDate} parameter.
1002         *
1003         * @param localDate
1004         *            the <code>LocalDate</code> to set the calendar to
1005         * @throws IllegalArgumentException
1006         *            if the {@link Calendar#ERA} is {@link GregorianCalendar#BC}
1007         */
1008        public JewishDate(LocalDate localDate) {
1009                setDate(localDate);
1010        }
1011
1012        /**
1013         * Sets the date based on a {@link java.util.Calendar Calendar} object. Modifies the Jewish date as well.
1014         * 
1015         * @param calendar
1016         *            the <code>Calendar</code> to set the calendar to
1017         * @throws IllegalArgumentException
1018         *             if the {@link Calendar#ERA} is {@link GregorianCalendar#BC}
1019         */
1020        public void setDate(Calendar calendar) {
1021                if (calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
1022                        throw new IllegalArgumentException("Calendars with a BC era are not supported. The year "
1023                                        + calendar.get(Calendar.YEAR) + " BC is invalid.");
1024                }
1025                gregorianMonth = calendar.get(Calendar.MONTH) + 1;
1026                gregorianDayOfMonth = calendar.get(Calendar.DATE);
1027                gregorianYear = calendar.get(Calendar.YEAR);
1028                gregorianAbsDate = gregorianDateToAbsDate(gregorianYear, gregorianMonth, gregorianDayOfMonth); // init the date
1029                absDateToJewishDate();
1030
1031                dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // set day of week
1032        }
1033
1034        /**
1035         * Sets the date based on a {@link java.util.Date Date} object. Modifies the Jewish date as well.
1036         * 
1037         * @param date
1038         *            the <code>Date</code> to set the calendar to
1039         * @throws IllegalArgumentException
1040         *             if the date would fall prior to the year 1 AD
1041         */
1042        public void setDate(Date date) {
1043                Calendar cal = Calendar.getInstance();
1044                cal.setTime(date);
1045                setDate(cal);
1046        }
1047
1048        /**
1049         * Sets the date based on a {@link java.time.LocalDate LocalDate} object. Modifies the Jewish date as well.
1050         *
1051         * @param localDate
1052         *            the <code>LocalDate</code> to set the calendar to
1053         * @throws IllegalArgumentException
1054         *             if the date would fall prior to the year 1 AD
1055         */
1056        public void setDate(LocalDate localDate) {
1057                Calendar cal = Calendar.getInstance();
1058                cal.set(localDate.getYear(), localDate.getMonthValue() - 1, localDate.getDayOfMonth());
1059                setDate(cal);
1060        }
1061
1062        /**
1063         * Sets the Gregorian Date, and updates the Jewish date accordingly. Like the Java Calendar A value of 0 is expected
1064         * for January.
1065         * 
1066         * @param year
1067         *            the Gregorian year
1068         * @param month
1069         *            the Gregorian month. Like the Java Calendar, this class expects 0 for January
1070         * @param dayOfMonth
1071         *            the Gregorian day of month. If this is &gt; the number of days in the month/year, the last valid date of
1072         *            the month will be set
1073         * @throws IllegalArgumentException
1074         *             if a year of &lt; 1, a month &lt; 0 or &gt; 11 or a day of month &lt; 1 is passed in
1075         */
1076        public void setGregorianDate(int year, int month, int dayOfMonth) {
1077                validateGregorianDate(year, month, dayOfMonth);
1078                setInternalGregorianDate(year, month + 1, dayOfMonth);
1079        }
1080
1081        /**
1082         * Sets the hidden internal representation of the Gregorian date , and updates the Jewish date accordingly. While
1083         * public getters and setters have 0 based months matching the Java Calendar classes, This class internally
1084         * represents the Gregorian month starting at 1. When this is called it will not adjust the month to match the Java
1085         * Calendar classes.
1086         * 
1087         * @param year the year
1088         * @param month the month
1089         * @param dayOfMonth the day of month
1090         */
1091        private void setInternalGregorianDate(int year, int month, int dayOfMonth) {
1092                // make sure date is a valid date for the given month, if not, set to last day of month
1093                if (dayOfMonth > getLastDayOfGregorianMonth(month, year)) {
1094                        dayOfMonth = getLastDayOfGregorianMonth(month, year);
1095                }
1096                // init month, date, year
1097                gregorianMonth = month;
1098                gregorianDayOfMonth = dayOfMonth;
1099                gregorianYear = year;
1100
1101                gregorianAbsDate = gregorianDateToAbsDate(gregorianYear, gregorianMonth, gregorianDayOfMonth); // init date
1102                absDateToJewishDate();
1103
1104                dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // set day of week
1105        }
1106
1107        /**
1108         * Sets the Jewish Date and updates the Gregorian date accordingly.
1109         * 
1110         * @param year
1111         *            the Jewish year. The year can't be negative
1112         * @param month
1113         *            the Jewish month starting with Nissan. A value of 1 is expected for Nissan ... 12 for Adar and 13 for
1114         *            Adar II. Use the constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar
1115         *            II) to avoid any confusion.
1116         * @param dayOfMonth
1117         *            the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only
1118         *            has 29 days, the day will be set as 29.
1119         * @throws IllegalArgumentException
1120         *             if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month &lt; 1 or &gt; 12 (or 13 on a
1121         *             leap year) or the day of month is &lt; 1 or &gt; 30 is passed in
1122         */
1123        public void setJewishDate(int year, int month, int dayOfMonth) {
1124                setJewishDate(year, month, dayOfMonth, 0, 0, 0);
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 Nissan. 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         * 
1140         * @param hours
1141         *            the hour of the day. Used for <em>molad</em> calculations
1142         * @param minutes
1143         *            the minutes. Used for <em>molad</em> calculations
1144         * @param chalakim
1145         *            the <em>chalakim</em> / parts. Used for <em>molad</em> calculations. The <em>chalakim</em> should not
1146         *            exceed 17. Minutes should be used for larger numbers.
1147         * 
1148         * @throws IllegalArgumentException
1149         *             if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month &lt; 1 or &gt; 12 (or 13 on a leap year), the day
1150         *             of month is &lt; 1 or &gt; 30, an hour &lt; 0 or &gt; 23, a minute &lt; 0 &gt; 59 or <em>chalakim</em> &lt; 0 &gt; 17. For
1151         *             larger a larger number of <em>chalakim</em> such as 793 (<em>TaShTzaG</em>) break the <em>chalakim</em> into minutes (18
1152         *             <em>chalakim</em> per minutes, so it would be 44 minutes and 1 <em>chelek</em> in the case of 793 (<em>TaShTzaG</em>).
1153         */
1154        public void setJewishDate(int year, int month, int dayOfMonth, int hours, int minutes, int chalakim) {
1155                validateJewishDate(year, month, dayOfMonth, hours, minutes, chalakim);
1156
1157                // if 30 is passed for a month that only has 29 days (for example by rolling the month from a month that had 30
1158                // days to a month that only has 29) set the date to 29th
1159                if (dayOfMonth > getDaysInJewishMonth(month, year)) {
1160                        dayOfMonth = getDaysInJewishMonth(month, year);
1161                }
1162
1163                jewishMonth = month;
1164                jewishDay = dayOfMonth;
1165                jewishYear = year;
1166                moladHours = hours;
1167                moladMinutes = minutes;
1168                moladChalakim = chalakim;
1169
1170                gregorianAbsDate = jewishDateToAbsDate(jewishYear, jewishMonth, jewishDay); // reset Gregorian date
1171                absDateToDate(gregorianAbsDate);
1172
1173                dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // reset day of week
1174        }
1175
1176        /**
1177         * Returns this object's date as a {@link java.util.Calendar} object.
1178         * 
1179         * @return The {@link java.util.Calendar}
1180         */
1181        public Calendar getGregorianCalendar() {
1182                Calendar calendar = Calendar.getInstance();
1183                calendar.set(getGregorianYear(), getGregorianMonth(), getGregorianDayOfMonth());
1184                return calendar;
1185        }
1186
1187        /**
1188         * Returns this object's date as a {@link java.time.LocalDate} object.
1189         *
1190         * @return The {@link java.time.LocalDate}
1191         */
1192        public LocalDate getLocalDate() {
1193                return LocalDate.of(getGregorianYear(), getGregorianMonth() + 1, getGregorianDayOfMonth());
1194        }
1195
1196        /**
1197         * Resets this date to the current system date.
1198         */
1199        public void resetDate() {
1200                Calendar calendar = Calendar.getInstance();
1201                setDate(calendar);
1202        }
1203
1204        /**
1205         * Returns a string containing the Jewish date in the form, "day Month, year" e.g. "21 Shevat, 5729". For more
1206         * complex formatting, use the formatter classes.
1207         * 
1208         * @return the Jewish date in the form "day Month, year" e.g. "21 Shevat, 5729"
1209         * @see HebrewDateFormatter#format(JewishDate)
1210         */
1211        public String toString() {
1212                return new HebrewDateFormatter().format(this);
1213        }
1214
1215        /**
1216         * Rolls the date, month or year forward by the amount passed in. It modifies both the Gregorian and Jewish dates accordingly.
1217         * If manipulation beyond the fields supported here is required, use the {@link Calendar} class {@link Calendar#add(int, int)}
1218         * or {@link Calendar#roll(int, int)} methods in the following manner.
1219         * 
1220         * <pre>
1221         * <code>
1222         *      Calendar cal = jewishDate.getTime(); // get a java.util.Calendar representation of the JewishDate
1223         *      cal.add(Calendar.MONTH, 3); // add 3 Gregorian months
1224         *      jewishDate.setDate(cal); // set the updated calendar back to this class
1225         * </code>
1226         * </pre>
1227         * 
1228         * @param field the calendar field to be forwarded. The must be {@link Calendar#DATE}, {@link Calendar#MONTH} or {@link Calendar#YEAR}
1229         * @param amount the positive amount to move forward
1230         * @throws IllegalArgumentException if the field is anything besides {@link Calendar#DATE}, {@link Calendar#MONTH} or {@link Calendar#YEAR}
1231         * or if the amount is less than 1
1232         * 
1233         * @see #back()
1234         * @see Calendar#add(int, int)
1235         * @see Calendar#roll(int, int)
1236         */
1237        public void forward(int field, int amount) {
1238                if (field != Calendar.DATE && field != Calendar.MONTH && field != Calendar.YEAR) {
1239                        throw new IllegalArgumentException("Unsupported field was passed to Forward. Only Calendar.DATE, Calendar.MONTH or Calendar.YEAR are supported.");
1240                }
1241                if (amount < 1) {
1242                        throw new IllegalArgumentException("JewishDate.forward() does not support amounts less than 1. See JewishDate.back()");
1243                }
1244                if (field == Calendar.DATE) {
1245                        // Change Gregorian date
1246                        for (int i = 0; i < amount; i++) {
1247                                if (gregorianDayOfMonth == getLastDayOfGregorianMonth(gregorianMonth, gregorianYear)) {
1248                                        gregorianDayOfMonth = 1;
1249                                        // if last day of year
1250                                        if (gregorianMonth == 12) {
1251                                                gregorianYear++;
1252                                                gregorianMonth = 1;
1253                                        } else {
1254                                                gregorianMonth++;
1255                                        }
1256                                } else { // if not last day of month
1257                                        gregorianDayOfMonth++;
1258                                }
1259                
1260                                // Change the Jewish Date
1261                                if (jewishDay == getDaysInJewishMonth()) {
1262                                        // if it last day of elul (i.e. last day of Jewish year)
1263                                        if (jewishMonth == ELUL) {
1264                                                jewishYear++;
1265                                                jewishMonth++;
1266                                                jewishDay = 1;
1267                                        } else if (jewishMonth == getLastMonthOfJewishYear(jewishYear)) {
1268                                                // if it is the last day of Adar, or Adar II as case may be
1269                                                jewishMonth = NISSAN;
1270                                                jewishDay = 1;
1271                                        } else {
1272                                                jewishMonth++;
1273                                                jewishDay = 1;
1274                                        }
1275                                } else { // if not last date of month
1276                                        jewishDay++;
1277                                }
1278                
1279                                if (dayOfWeek == 7) { // if last day of week, loop back to Sunday
1280                                        dayOfWeek = 1;
1281                                } else {
1282                                        dayOfWeek++;
1283                                }
1284                
1285                                gregorianAbsDate++; // increment the absolute date
1286                        }
1287                } else if (field == Calendar.MONTH) {
1288                        forwardJewishMonth(amount);
1289                } else {
1290                        setJewishYear(getJewishYear() + amount);
1291                }
1292        }
1293        
1294        /**
1295         * Forward the Jewish date by the number of months passed in.
1296         * FIXME: Deal with forwarding a date such as 30 Nissan by a month. 30 Iyar does not exist. This should be dealt with similar to 
1297         * the way that the Java Calendar behaves (not that simple since there is a difference between add() or roll().
1298         * 
1299         * @throws IllegalArgumentException if the amount is less than 1
1300         * @param amount the number of months to roll the month forward
1301         */
1302        private void forwardJewishMonth(int amount) {
1303                if (amount < 1) {
1304                        throw new IllegalArgumentException("the amount of months to forward has to be greater than zero.");
1305                }
1306                for (int i = 0; i < amount; i++) {
1307                        if (getJewishMonth() == ELUL) {
1308                                setJewishMonth(TISHREI);
1309                                setJewishYear(getJewishYear() + 1);
1310                        } else if ((! isJewishLeapYear() && getJewishMonth() == ADAR)
1311                                                || (isJewishLeapYear() && getJewishMonth() == ADAR_II)){
1312                                setJewishMonth(NISSAN);
1313                        } else {
1314                                setJewishMonth(getJewishMonth() + 1);
1315                        }
1316                }
1317        }
1318
1319        /**
1320         * Rolls the date back by 1 day. It modifies both the Gregorian and Jewish dates accordingly. The API does not
1321         * currently offer the ability to forward more than one day at a time, or to forward by month or year. If such
1322         * manipulation is required use the {@link Calendar} class {@link Calendar#add(int, int)} or
1323         * {@link Calendar#roll(int, int)} methods in the following manner.
1324         * 
1325         * <pre>
1326         * <code>
1327         *      Calendar cal = jewishDate.getTime(); // get a java.util.Calendar representation of the JewishDate
1328         *      cal.add(Calendar.MONTH, -3); // subtract 3 Gregorian months
1329         *      jewishDate.setDate(cal); // set the updated calendar back to this class
1330         * </code>
1331         * </pre>
1332         * 
1333         * @see #back()
1334         * @see Calendar#add(int, int)
1335         * @see Calendar#roll(int, int)
1336         */
1337        public void back() {
1338                // Change Gregorian date
1339                if (gregorianDayOfMonth == 1) { // if first day of month
1340                        if (gregorianMonth == 1) { // if first day of year
1341                                gregorianMonth = 12;
1342                                gregorianYear--;
1343                        } else {
1344                                gregorianMonth--;
1345                        }
1346                        // change to last day of previous month
1347                        gregorianDayOfMonth = getLastDayOfGregorianMonth(gregorianMonth, gregorianYear);
1348                } else {
1349                        gregorianDayOfMonth--;
1350                }
1351                // change Jewish date
1352                if (jewishDay == 1) { // if first day of the Jewish month
1353                        if (jewishMonth == NISSAN) {
1354                                jewishMonth = getLastMonthOfJewishYear(jewishYear);
1355                        } else if (jewishMonth == TISHREI) { // if Rosh Hashana
1356                                jewishYear--;
1357                                jewishMonth--;
1358                        } else {
1359                                jewishMonth--;
1360                        }
1361                        jewishDay = getDaysInJewishMonth();
1362                } else {
1363                        jewishDay--;
1364                }
1365
1366                if (dayOfWeek == 1) { // if first day of week, loop back to Saturday
1367                        dayOfWeek = 7;
1368                } else {
1369                        dayOfWeek--;
1370                }
1371                gregorianAbsDate--; // change the absolute date
1372        }
1373
1374        /**
1375         * Indicates whether some other object is "equal to" this one.
1376         * @see Object#equals(Object)
1377         */
1378        public boolean equals(Object object) {
1379                if (this == object) {
1380                        return true;
1381                }
1382                if (!(object instanceof JewishDate)) {
1383                        return false;
1384                }
1385                JewishDate jewishDate = (JewishDate) object;
1386                return gregorianAbsDate == jewishDate.getAbsDate();
1387        }
1388
1389        /**
1390         * Compares two dates as per the compareTo() method in the Comparable interface. Returns a value less than 0 if this
1391         * date is "less than" (before) the date, greater than 0 if this date is "greater than" (after) the date, or 0 if
1392         * they are equal.
1393         */
1394        public int compareTo(JewishDate jewishDate) {
1395                return Integer.compare(gregorianAbsDate, jewishDate.getAbsDate());
1396        }
1397
1398        /**
1399         * Returns the Gregorian month (between 0-11).
1400         * 
1401         * @return the Gregorian month (between 0-11). Like the java.util.Calendar, months are 0 based.
1402         */
1403        public int getGregorianMonth() {
1404                return gregorianMonth - 1;
1405        }
1406
1407        /**
1408         * Returns the Gregorian day of the month.
1409         * 
1410         * @return the Gregorian day of the mont
1411         */
1412        public int getGregorianDayOfMonth() {
1413                return gregorianDayOfMonth;
1414        }
1415
1416        /**
1417         * Returns the Gregorian year.
1418         * 
1419         * @return the Gregorian year
1420         */
1421        public int getGregorianYear() {
1422                return gregorianYear;
1423        }
1424
1425        /**
1426         * Returns the Jewish month 1-12 (or 13 years in a leap year). The month count starts with 1 for Nissan and goes to
1427         * 13 for Adar II
1428         * 
1429         * @return the Jewish month from 1 to 12 (or 13 years in a leap year). The month count starts with 1 for Nissan and
1430         *         goes to 13 for Adar II
1431         */
1432        public int getJewishMonth() {
1433                return jewishMonth;
1434        }
1435
1436        /**
1437         * Returns the Jewish day of month.
1438         * 
1439         * @return the Jewish day of the month
1440         */
1441        public int getJewishDayOfMonth() {
1442                return jewishDay;
1443        }
1444
1445        /**
1446         * Returns the Jewish year.
1447         * 
1448         * @return the Jewish year
1449         */
1450        public int getJewishYear() {
1451                return jewishYear;
1452        }
1453
1454        /**
1455         * Returns the day of the week as a number between 1-7.
1456         * 
1457         * @return the day of the week as a number between 1-7.
1458         */
1459        public int getDayOfWeek() {
1460                return dayOfWeek;
1461        }
1462
1463        /**
1464         * Sets the Gregorian month.
1465         * 
1466         * @param month
1467         *            the Gregorian month
1468         * 
1469         * @throws IllegalArgumentException
1470         *             if a month &lt; 0 or &gt; 11 is passed in
1471         */
1472        public void setGregorianMonth(int month) {
1473                validateGregorianMonth(month);
1474                setInternalGregorianDate(gregorianYear, month + 1, gregorianDayOfMonth);
1475        }
1476
1477        /**
1478         * sets the Gregorian year.
1479         * 
1480         * @param year
1481         *            the Gregorian year.
1482         * @throws IllegalArgumentException
1483         *             if a year of &lt; 1 is passed in
1484         */
1485        public void setGregorianYear(int year) {
1486                validateGregorianYear(year);
1487                setInternalGregorianDate(year, gregorianMonth, gregorianDayOfMonth);
1488        }
1489
1490        /**
1491         * sets the Gregorian Day of month.
1492         * 
1493         * @param dayOfMonth
1494         *            the Gregorian Day of month.
1495         * @throws IllegalArgumentException
1496         *             if the day of month of &lt; 1 is passed in
1497         */
1498        public void setGregorianDayOfMonth(int dayOfMonth) {
1499                validateGregorianDayOfMonth(dayOfMonth);
1500                setInternalGregorianDate(gregorianYear, gregorianMonth, dayOfMonth);
1501        }
1502
1503        /**
1504         * sets the Jewish month.
1505         * 
1506         * @param month
1507         *            the Jewish month from 1 to 12 (or 13 years in a leap year). The month count starts with 1 for Nissan
1508         *            and goes to 13 for Adar II
1509         * @throws IllegalArgumentException
1510         *             if a month &lt; 1 or &gt; 12 (or 13 on a leap year) is passed in
1511         */
1512        public void setJewishMonth(int month) {
1513                setJewishDate(jewishYear, month, jewishDay);
1514        }
1515
1516        /**
1517         * sets the Jewish year.
1518         * 
1519         * @param year
1520         *            the Jewish year
1521         * @throws IllegalArgumentException
1522         *             if a year of &lt; 3761 is passed in. The same will happen if the year is 3761 and the month and day
1523         *             previously set are &lt; 18 Teves (prior to Jan 1, 1 AD)
1524         */
1525        public void setJewishYear(int year) {
1526                setJewishDate(year, jewishMonth, jewishDay);
1527        }
1528
1529        /**
1530         * sets the Jewish day of month.
1531         * 
1532         * @param dayOfMonth
1533         *            the Jewish day of month
1534         * @throws IllegalArgumentException
1535         *             if the day of month is &lt; 1 or &gt; 30 is passed in
1536         */
1537        public void setJewishDayOfMonth(int dayOfMonth) {
1538                setJewishDate(jewishYear, jewishMonth, dayOfMonth);
1539        }
1540
1541        /**
1542         * A method that creates a <a href="http://en.wikipedia.org/wiki/Object_copy#Deep_copy">deep copy</a> of the object.
1543         * 
1544         * @see Object#clone()
1545         */
1546        public Object clone() {
1547                JewishDate clone = null;
1548                try {
1549                        clone = (JewishDate) super.clone();
1550                } catch (CloneNotSupportedException cnse) {
1551                        // Required by the compiler. Should never be reached since we implement clone()
1552                }
1553                if (clone != null) {
1554                        clone.setInternalGregorianDate(gregorianYear, gregorianMonth, gregorianDayOfMonth);
1555                }
1556                return clone;
1557        }
1558
1559        /**
1560         * Overrides {@link Object#hashCode()}.
1561         * @see Object#hashCode()
1562         */
1563        public int hashCode() {
1564                int result = 17;
1565                result = 37 * result + getClass().hashCode(); // needed or this and subclasses will return identical hash
1566                result += 37 * result + gregorianAbsDate;
1567                return result;
1568        }
1569}