diff --git a/src/main/java/com/kosherjava/zmanim/ComprehensiveZmanimCalendar.java b/src/main/java/com/kosherjava/zmanim/ComprehensiveZmanimCalendar.java index 5fdf35c3..d22cba56 100644 --- a/src/main/java/com/kosherjava/zmanim/ComprehensiveZmanimCalendar.java +++ b/src/main/java/com/kosherjava/zmanim/ComprehensiveZmanimCalendar.java @@ -3444,7 +3444,7 @@ public Instant getTchilasZmanKidushLevana3Days(Instant alos, Instant tzais) { //Get the following month's zman kiddush Levana for the extreme case of Rapa Iti in French Polynesia on Dec 2027 when // kiddush Levana can be said on Rosh Chodesh (the evening of the 30th). See Rabbi Dovid Heber's Shaarei Zmanim chapter 4 (page 32) if (zman == null && jewishCalendar.getJewishDayOfMonth() == 30) { - jewishCalendar.forward(Calendar.MONTH, 1); + jewishCalendar.addMonths(1); zman = getMoladBasedTime(jewishCalendar.getTchilasZmanKidushLevana3Days(), null, null, true); } @@ -3476,7 +3476,7 @@ public Instant getZmanMolad() { // deal with molad that happens on the end of the previous month if (molad == null && jewishCalendar.getJewishDayOfMonth() > 26) { - jewishCalendar.forward(Calendar.MONTH, 1); + jewishCalendar.addMonths(1); molad = getMoladBasedTime(jewishCalendar.getMoladAsInstant(), null, null, true); } return molad; diff --git a/src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java b/src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java index 8cfd7274..2bb1f04a 100644 --- a/src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java +++ b/src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java @@ -1086,8 +1086,7 @@ public void setCandleLightingOffset(double candleLightingOffset) { */ public boolean isAssurBemlacha(Instant currentTime, Instant tzais, boolean inIsrael) { JewishCalendar jewishCalendar = new JewishCalendar(); - jewishCalendar.setGregorianDate(getLocalDate().getYear(), getLocalDate().getMonthValue(), - getLocalDate().getDayOfMonth()); + jewishCalendar.setGregorianDate(getLocalDate()); jewishCalendar.setInIsrael(inIsrael); diff --git a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/HebrewDateFormatter.java b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/HebrewDateFormatter.java index 71fa8f12..13497b3d 100644 --- a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/HebrewDateFormatter.java +++ b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/HebrewDateFormatter.java @@ -654,7 +654,7 @@ public String formatDayOfWeek(JewishDate jewishDate) { return getTransliteratedShabbosDayOfWeek().substring(0,3); } } else { - return weekFormat.format(jewishDate.getGregorianCalendar().getTime()); + return weekFormat.format(jewishDate.getLocalDate()); } } } diff --git a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishCalendar.java b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishCalendar.java index c2bd6960..9541b27e 100644 --- a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishCalendar.java +++ b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishCalendar.java @@ -20,9 +20,10 @@ import java.time.Duration; import java.time.Instant; import java.time.LocalDate; +import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.Calendar; +import java.util.Calendar; // We still use the old Calendar.WEEKDAY constants /** * The JewishCalendar extends the JewishDate class and adds calendar methods. @@ -506,12 +507,12 @@ public Parsha getUpcomingParshah() { JewishCalendar clone = (JewishCalendar) clone(); int daysToShabbos = (Calendar.SATURDAY - getDayOfWeek() + 7) % 7; if (getDayOfWeek() != Calendar.SATURDAY) { - clone.forward(Calendar.DATE, daysToShabbos); + clone.addDays(daysToShabbos); } else { - clone.forward(Calendar.DATE, 7); + clone.addDays( 7); } while(clone.getParshah() == Parsha.NONE) { //Yom Kippur / Sukkos or Pesach with 2 potential non-parsha Shabbosim in a row - clone.forward(Calendar.DATE, 7); + clone.addDays(7); } return clone.getParshah(); } @@ -1233,16 +1234,9 @@ public Instant getMoladAsInstant() { int seconds = (int) moladSeconds; int nanos = (int) ((moladSeconds - seconds) * 1_000_000_000); // convert remainder to nanos - ZonedDateTime moladZdt = ZonedDateTime.of( - molad.getGregorianYear(), - molad.getGregorianMonth() + 1, // 1-based FIXME - molad.getGregorianDayOfMonth(), - molad.getMoladHours(), - molad.getMoladMinutes(), - seconds, - nanos, - jerusalemStandardOffset - ); + LocalTime time = LocalTime.of(molad.getMoladHours(),molad.getMoladMinutes(),seconds,nanos); + + ZonedDateTime moladZdt = ZonedDateTime.of(molad.getLocalDate(),time,jerusalemStandardOffset); // Har Habayis at a longitude of 35.2354 offset vs longitude 35 in standard time, so we subtract the time difference // of 20.94 minutes (20 minutes and 56 seconds and 496 millis) to get to Standard time from local mean time @@ -1402,9 +1396,9 @@ public boolean equals(Object object) { if (this == object) { return true; } - if (!(object instanceof JewishCalendar)) { - return false; - } + if (object == null || getClass() != object.getClass()) { + return false; + } JewishCalendar jewishCalendar = (JewishCalendar) object; return getAbsDate() == jewishCalendar.getAbsDate() && getInIsrael() == jewishCalendar.getInIsrael(); } @@ -1414,9 +1408,8 @@ public boolean equals(Object object) { * @see Object#hashCode() */ public int hashCode() { - int result = 17; - result = 37 * result + getClass().hashCode(); // needed or this and subclasses will return identical hash - result += 37 * result + getAbsDate() + (getInIsrael() ? 1 : 3); - return result; + int result = Integer.hashCode(getAbsDate()); + result = 31 * result + Boolean.hashCode(getInIsrael()); + return result; } } diff --git a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishDate.java b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishDate.java index db74d09d..5a668f0f 100644 --- a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishDate.java +++ b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishDate.java @@ -17,9 +17,8 @@ package com.kosherjava.zmanim.hebrewcalendar; import java.time.LocalDate; +import java.time.YearMonth; import java.time.ZonedDateTime; -import java.util.Calendar; -import java.util.GregorianCalendar; /** * The JewishDate is the base calendar class, that supports maintenance of a {@link java.util.GregorianCalendar} @@ -32,21 +31,21 @@ * href="http://en.wikipedia.org/wiki/Hillel_II">Hillel II's (Hakatan's) calendar (4119 in the Jewish Calendar / 359 * CE Julian as recorded by Rav Hai Gaon) would be just an * approximation. - * + * * This open source Java code was written by Avrom Finkelstien from his C++ * code. It was refactored to fit the KosherJava Zmanim API with simplification of the code, enhancements and some bug * fixing. - * + * * Some of Avrom's original C++ code was translated from * C/C++ code in * Calendrical Calculations by Nachum Dershowitz and Edward M. * Reingold, Software-- Practice & Experience, vol. 20, no. 9 (September, 1990), pp. 899- 928. Any method with the mark * "ND+ER" indicates that the method was taken from this source with minor modifications. - * + * * If you are looking for a class that implements a Jewish calendar version of the Calendar class, one is available from * the ICU (International Components for Unicode) project, formerly part of * IBM's DeveloperWorks. - * + * * @see JewishCalendar * @see HebrewDateFormatter * @see java.util.Date @@ -55,1495 +54,1116 @@ * @author © Eliyahu Hershfeld 2011 - 2026 */ public class JewishDate implements Comparable, Cloneable { - /** - * Value of the month field indicating Nissan, the first numeric month of the year in the Jewish calendar. With the - * year starting at {@link #TISHREI}, it would actually be the 7th (or 8th in a {@link #isJewishLeapYear() leap - * year}) month of the year. - */ - public static final int NISSAN = 1; - - /** - * Value of the month field indicating Iyar, the second numeric month of the year in the Jewish calendar. With the - * year starting at {@link #TISHREI}, it would actually be the 8th (or 9th in a {@link #isJewishLeapYear() leap - * year}) month of the year. - */ - public static final int IYAR = 2; - - /** - * Value of the month field indicating Sivan, the third numeric month of the year in the Jewish calendar. With the - * year starting at {@link #TISHREI}, it would actually be the 9th (or 10th in a {@link #isJewishLeapYear() leap - * year}) month of the year. - */ - public static final int SIVAN = 3; - - /** - * Value of the month field indicating Tammuz, the fourth numeric month of the year in the Jewish calendar. With the - * year starting at {@link #TISHREI}, it would actually be the 10th (or 11th in a {@link #isJewishLeapYear() leap - * year}) month of the year. - */ - public static final int TAMMUZ = 4; - - /** - * Value of the month field indicating Av, the fifth numeric month of the year in the Jewish calendar. With the year - * starting at {@link #TISHREI}, it would actually be the 11th (or 12th in a {@link #isJewishLeapYear() leap year}) - * month of the year. - */ - public static final int AV = 5; - - /** - * Value of the month field indicating Elul, the sixth numeric month of the year in the Jewish calendar. With the - * year starting at {@link #TISHREI}, it would actually be the 12th (or 13th in a {@link #isJewishLeapYear() leap - * year}) month of the year. - */ - public static final int ELUL = 6; - - /** - * Value of the month field indicating Tishrei, the seventh numeric month of the year in the Jewish calendar. With - * the year starting at this month, it would actually be the 1st month of the year. - */ - public static final int TISHREI = 7; - - /** - * Value of the month field indicating Cheshvan/marcheshvan, the eighth numeric month of the year in the Jewish - * calendar. With the year starting at {@link #TISHREI}, it would actually be the 2nd month of the year. - */ - public static final int CHESHVAN = 8; - - /** - * Value of the month field indicating Kislev, the ninth numeric month of the year in the Jewish calendar. With the - * year starting at {@link #TISHREI}, it would actually be the 3rd month of the year. - */ - public static final int KISLEV = 9; - - /** - * Value of the month field indicating Teves, the tenth numeric month of the year in the Jewish calendar. With the - * year starting at {@link #TISHREI}, it would actually be the 4th month of the year. - */ - public static final int TEVES = 10; - - /** - * Value of the month field indicating Shevat, the eleventh numeric month of the year in the Jewish calendar. With - * the year starting at {@link #TISHREI}, it would actually be the 5th month of the year. - */ - public static final int SHEVAT = 11; - - /** - * Value of the month field indicating Adar (or Adar I in a {@link #isJewishLeapYear() leap year}), the twelfth - * numeric month of the year in the Jewish calendar. With the year starting at {@link #TISHREI}, it would actually - * be the 6th month of the year. - */ - public static final int ADAR = 12; - - /** - * Value of the month field indicating Adar II, the leap (intercalary or embolismic) thirteenth (Undecimber) numeric - * month of the year added in Jewish {@link #isJewishLeapYear() leap year}). The leap years are years 3, 6, 8, 11, - * 14, 17 and 19 of a 19-year cycle. With the year starting at {@link #TISHREI}, it would actually be the 7th month - * of the year. - */ - public static final int ADAR_II = 13; - - /** - * the Jewish epoch using the RD (Rata Die/Fixed Date or Reingold Dershowitz) day used in Calendrical Calculations. - * Day 1 is January 1, 0001 of the Gregorian calendar - */ - private static final int JEWISH_EPOCH = -1373429; - - /** The number of chalakim (18) in a minute.*/ - private static final int CHALAKIM_PER_MINUTE = 18; - /** The number of chalakim (1080) in an hour.*/ - private static final int CHALAKIM_PER_HOUR = 1080; - /** The number of chalakim (25,920) in a 24-hour day .*/ - private static final int CHALAKIM_PER_DAY = 25920; // 24 * 1080 - /** The number of chalakim in an average Jewish month. A month has 29 days, 12 hours and 793 - * chalakim (44 minutes and 3.3 seconds) for a total of 765,433 chalakim*/ - private static final long CHALAKIM_PER_MONTH = 765433; // (29 * 24 + 12) * 1080 + 793 - /** - * Days from the beginning of Sunday till molad BaHaRaD. Calculated as 1 day, 5 hours and 204 chalakim = - * (24 + 5) * 1080 + 204 = 31524 - */ - private static final int CHALAKIM_MOLAD_TOHU = 31524; - - /** - * A short year where both {@link #CHESHVAN} and {@link #KISLEV} are 29 days. - * - * @see #getCheshvanKislevKviah() - * @see HebrewDateFormatter#getFormattedKviah(int) - */ - public static final int CHASERIM = 0; - - /** - * An ordered year where {@link #CHESHVAN} is 29 days and {@link #KISLEV} is 30 days. - * - * @see #getCheshvanKislevKviah() - * @see HebrewDateFormatter#getFormattedKviah(int) - */ - public static final int KESIDRAN = 1; - - /** - * A long year where both {@link #CHESHVAN} and {@link #KISLEV} are 30 days. - * - * @see #getCheshvanKislevKviah() - * @see HebrewDateFormatter#getFormattedKviah(int) - */ - public static final int SHELAIMIM = 2; - - /** the internal Jewish month.*/ - private int jewishMonth; - /** the internal Jewish day.*/ - private int jewishDay; - /** the internal Jewish year.*/ - private int jewishYear; - /** the internal count of molad hours.*/ - private int moladHours; - /** the internal count of molad minutes.*/ - private int moladMinutes; - /** the internal count of molad chalakim.*/ - private int moladChalakim; - - /** - * Returns the molad hours. Only a JewishDate object populated with {@link #getMolad()}, - * {@link #setJewishDate(int, int, int, int, int, int)} or {@link #setMoladHours(int)} will have this field - * populated. A regular JewishDate object will have this field set to 0. - * - * @return the molad hours - * @see #setMoladHours(int) - * @see #getMolad() - * @see #setJewishDate(int, int, int, int, int, int) - */ - public int getMoladHours() { - return moladHours; - } - - /** - * Sets the molad hours. - * - * @param moladHours - * the molad hours to set - * @see #getMoladHours() - * @see #getMolad() - * @see #setJewishDate(int, int, int, int, int, int) - * - */ - public void setMoladHours(int moladHours) { - this.moladHours = moladHours; - } - - /** - * Returns the molad minutes. Only an object populated with {@link #getMolad()}, - * {@link #setJewishDate(int, int, int, int, int, int)} or or {@link #setMoladMinutes(int)} will have these fields - * populated. A regular JewishDate object will have this field set to 0. - * - * @return the molad minutes - * @see #setMoladMinutes(int) - * @see #getMolad() - * @see #setJewishDate(int, int, int, int, int, int) - */ - public int getMoladMinutes() { - return moladMinutes; - } - - /** - * Sets the molad minutes. The expectation is that the traditional minute-less chalakim will be broken out to - * minutes and {@link #setMoladChalakim(int) chalakim / parts} , so 793 (TaShTZaG) parts would have the minutes set to - * 44 and chalakim to 1. - * - * @param moladMinutes - * the molad minutes to set - * @see #getMoladMinutes() - * @see #setMoladChalakim(int) - * @see #getMolad() - * @see #setJewishDate(int, int, int, int, int, int) - * - */ - public void setMoladMinutes(int moladMinutes) { - this.moladMinutes = moladMinutes; - } - - /** - * Sets the molad chalakim/parts. The expectation is that the traditional minute-less chalakim will be broken - * out to {@link #setMoladMinutes(int) minutes} and chalakim, so 793 (TaShTZaG) parts would have the minutes set to 44 and - * chalakim to 1. - * - * @param moladChalakim - * the molad chalakim / parts to set - * @see #getMoladChalakim() - * @see #setMoladMinutes(int) - * @see #getMolad() - * @see #setJewishDate(int, int, int, int, int, int) - * - */ - public void setMoladChalakim(int moladChalakim) { - this.moladChalakim = moladChalakim; - } - - /** - * Returns the molad chalakim / parts. Only an object populated with {@link #getMolad()}, - * {@link #setJewishDate(int, int, int, int, int, int)} or or {@link #setMoladChalakim(int)} will have these fields - * populated. A regular JewishDate object will have this field set to 0. - * - * @return the molad chalakim / parts - * @see #setMoladChalakim(int) - * @see #getMolad() - * @see #setJewishDate(int, int, int, int, int, int) - */ - public int getMoladChalakim() { - return moladChalakim; - } - - /** - * Returns the last day in a gregorian month - * - * @param month - * the Gregorian month - * @return the last day of the Gregorian month - */ - int getLastDayOfGregorianMonth(int month) { - return getLastDayOfGregorianMonth(month, gregorianYear); - } - - /** - * Returns is the year passed in is a Gregorian leap year. - * @param year the Gregorian year - * @return if the year in question is a leap year. - */ - boolean isGregorianLeapYear(int year) { - return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); - } - - /** - * The month, where 1 == January, 2 == February, etc... Note that this is different than Java's Calendar class - * where January == 0. - */ - private int gregorianMonth; - - /** The day of the Gregorian month */ - private int gregorianDayOfMonth; - - /** The Gregorian year */ - private int gregorianYear; - - /** 1 == Sunday, 2 == Monday, etc... */ - private int dayOfWeek; - - /** Returns the absolute date (days since January 1, 0001 of the Gregorian calendar). - * @see #getAbsDate() - * @see #absDateToJewishDate() - */ - private int gregorianAbsDate; - - /** - * Returns the number of days in a given month in a given month and year. - * - * @param month - * the month. As with other cases in this class, this is 1-based, not zero-based. - * @param year - * the year (only impacts February) - * @return the number of days in the month in the given year - */ - private static int getLastDayOfGregorianMonth(int month, int year) { - switch (month) { - case 2: - if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { - return 29; - } else { - return 28; - } - case 4: - case 6: - case 9: - case 11: - return 30; - default: - return 31; - } - } - - /** - * Computes the Gregorian date from the absolute date. ND+ER - * @param absDate the absolute date - */ - private void absDateToDate(int absDate) { - int year = absDate / 366; // Search forward year by year from approximate year - while (absDate >= gregorianDateToAbsDate(year + 1, 1, 1)) { - year++; - } - - int month = 1; // Search forward month by month from January - while (absDate > gregorianDateToAbsDate(year, month, getLastDayOfGregorianMonth(month, year))) { - month++; - } - - int dayOfMonth = absDate - gregorianDateToAbsDate(year, month, 1) + 1; - setInternalGregorianDate(year, month, dayOfMonth); - } - - /** - * Returns the absolute date (days since January 1, 0001 of the Gregorian calendar). - * - * @return the number of days since January 1, 1 - */ - public int getAbsDate() { - return gregorianAbsDate; - } - - /** - * Computes the absolute date from a Gregorian date. ND+ER - * - * @param year - * the Gregorian year - * @param month - * the Gregorian month. Unlike the Java Calendar where January has the value of 0,This expects a 1 for - * January - * @param dayOfMonth - * the day of the month (1st, 2nd, etc...) - * @return the absolute Gregorian day - */ - private static int gregorianDateToAbsDate(int year, int month, int dayOfMonth) { - int absDate = dayOfMonth; - for (int m = month - 1; m > 0; m--) { - absDate += getLastDayOfGregorianMonth(m, year); // days in prior months of the year - } - return (absDate // days this year - + 365 * (year - 1) // days in previous years ignoring leap days - + (year - 1) / 4 // Julian leap days before this year - - (year - 1) / 100 // minus prior century years - + (year - 1) / 400); // plus prior years divisible by 400 - } - - /** - * 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. - * - * @param year - * the Jewish year. - * @return true if it is a leap year - * @see #isJewishLeapYear() - */ - private static boolean isJewishLeapYear(int year) { - return ((7 * year) + 1) % 19 < 7; - } - - /** - * 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 - * cycle are leap years. - * - * @return true if it is a leap year - * @see #isJewishLeapYear(int) - */ - public boolean isJewishLeapYear() { - return isJewishLeapYear(getJewishYear()); - } - - /** - * Returns the last month of a given Jewish year. This will be 12 on a non {@link #isJewishLeapYear(int) leap year} - * or 13 on a leap year. - * - * @param year - * the Jewish year. - * @return 12 on a non leap year or 13 on a leap year - * @see #isJewishLeapYear(int) - */ - private static int getLastMonthOfJewishYear(int year) { - return isJewishLeapYear(year) ? ADAR_II : ADAR; - } - - /** - * Returns the number of days elapsed from the Sunday prior to the start of the Jewish calendar to the mean - * conjunction of Tishri of the Jewish year. - * - * @param year - * the Jewish year - * @return the number of days elapsed from prior to the molad Tohu BaHaRaD (Be = Monday, Ha = 5 - * hours and RaD = 204 chalakim / parts) prior to the start of the Jewish calendar, to - * the mean conjunction of Tishri of the Jewish year. BeHaRaD is 23:11:20 on Sunday night(5 hours 204/1080 - * chalakim after sunset on Sunday evening). - */ - public static int getJewishCalendarElapsedDays(int year) { - long chalakimSince = getChalakimSinceMoladTohu(year, TISHREI); - int moladDay = (int) (chalakimSince / (long) CHALAKIM_PER_DAY); - int moladParts = (int) (chalakimSince - moladDay * (long) CHALAKIM_PER_DAY); - // delay Rosh Hashana for the 4 dechiyos - return addDechiyos(year, moladDay, moladParts); - } - - /** - * Adds the 4 dechiyos for molad Tishrei. These are: - *
    - *
  1. Lo ADU Rosh - Rosh Hashana can't fall on a Sunday, Wednesday or Friday. If the molad fell on one - * of these days, Rosh Hashana is delayed to the following day.
  2. - *
  3. Molad Zaken - If the molad of Tishrei falls after 12 noon, Rosh Hashana is delayed to the following - * day. If the following day is ADU, it will be delayed an additional day.
  4. - *
  5. GaTRaD - If on a non leap year the molad of Tishrei falls on a Tuesday (Ga) on or after 9 hours - * (T) and (RaD 204 chalakim it is delayed till Thursday (one day delay, plus one day for - * Lo ADU Rosh)
  6. - *
  7. BeTuTaKPaT - if the year following a leap year falls on a Monday (Be) on or after 15 hours - * (Tu) and 589 chalakim (TaKPaT) it is delayed till Tuesday
  8. - *
- * - * @param year the year - * @param moladDay the molad day - * @param moladParts the molad parts - * @return the number of elapsed days in the JewishCalendar adjusted for the 4 dechiyos. - */ - private static int addDechiyos(int year, int moladDay, int moladParts) { - int roshHashanaDay = moladDay; // if no dechiyos - // delay Rosh Hashana for the dechiyos of the Molad - new moon 1 - Molad Zaken, 2- GaTRaD 3- BeTuTaKPaT - if ((moladParts >= 19440) // Dechiya of Molad Zaken - molad is >= midday (18 hours * 1080 chalakim) - || (((moladDay % 7) == 2) // start Dechiya of GaTRaD - Ga = is a Tuesday - && (moladParts >= 9924) // TRaD = 9 hours, 204 parts or later (9 * 1080 + 204) - && !isJewishLeapYear(year)) // of a non-leap year - end Dechiya of GaTRaD - || (((moladDay % 7) == 1) // start Dechiya of BeTuTaKPaT - Be = is on a Monday - && (moladParts >= 16789) // TUTaKPaT part of BeTuTaKPaT = 15 hours, 589 parts or later (15 * 1080 + 589) - && (isJewishLeapYear(year - 1)))) { // in a year following a leap year - end Dechiya of BeTuTaKPaT - roshHashanaDay += 1; // Then postpone Rosh HaShanah one day - } - // start 4th Dechiya - Lo ADU Rosh - Rosh Hashana can't occur on A- sunday, D- Wednesday, U - Friday - if (((roshHashanaDay % 7) == 0)// If Rosh HaShanah would occur on Sunday, - || ((roshHashanaDay % 7) == 3) // or Wednesday, - || ((roshHashanaDay % 7) == 5)) { // or Friday - end 4th Dechiya - Lo ADU Rosh - roshHashanaDay = roshHashanaDay + 1; // Then postpone it one (more) day - } - return roshHashanaDay; - } - - /** - * Returns the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu - * to the year and month passed in. - * - * @param year - * the Jewish year - * @param month - * the Jewish month the Jewish month, with the month numbers starting from Nissan. Use the JewishDate - * constants such as {@link JewishDate#TISHREI}. - * @return the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu - */ - private static long getChalakimSinceMoladTohu(int year, int month) { - // Jewish lunar month = 29 days, 12 hours and 793 chalakim - // chalakim since Molad Tohu BeHaRaD - 1 day, 5 hours and 204 chalakim - int monthOfYear = getJewishMonthOfYear(year, month); - int monthsElapsed = (235 * ((year - 1) / 19)) // Months in complete 19-year lunar (Metonic) cycles so far - + (12 * ((year - 1) % 19)) // Regular months in this cycle - + ((7 * ((year - 1) % 19) + 1) / 19) // Leap months this cycle - + (monthOfYear - 1); // add elapsed months till the start of the molad of the month - // return chalakim prior to BeHaRaD + number of chalakim since - return CHALAKIM_MOLAD_TOHU + (CHALAKIM_PER_MONTH * monthsElapsed); - } - - /** - * Returns the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu - * to the Jewish year and month that this Object is set to. - * - * @return the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu - */ - public long getChalakimSinceMoladTohu() { - return getChalakimSinceMoladTohu(jewishYear, jewishMonth); - } - - /** - * Converts the {@link JewishDate#NISSAN} based constants used by this class to numeric month starting from - * {@link JewishDate#TISHREI}. This is required for molad calculations. - * - * @param year - * The Jewish year - * @param month - * The Jewish Month - * @return the Jewish month of the year starting with Tishrei - */ - private static int getJewishMonthOfYear(int year, int month) { - boolean isLeapYear = isJewishLeapYear(year); - return (month + (isLeapYear ? 6 : 5)) % (isLeapYear ? 13 : 12) + 1; - } - - /** - * Validates the components of a Jewish date for validity. It will throw an {@link IllegalArgumentException} if the Jewish - * date is earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month < 1 or > 12 (or 13 on a {@link #isJewishLeapYear(int) - * leap year}), the day of month is < 1 or > 30, an hour < 0 or > 23, a minute < 0 or > 59 or - * chalakim < 0 or > 17. For larger a larger number of chalakim 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). - * - * @param year - * the Jewish year to validate. It will reject any year <= 3761 (lower than the year 1 Gregorian). - * @param month - * the Jewish month to validate. It will reject a month < 1 or > 12 (or 13 on a leap year) . - * @param dayOfMonth - * the day of the Jewish month to validate. It will reject any value < 1 or > 30 TODO: check calling - * methods to see if there is any reason that the class can validate that 30 is invalid for some months. - * @param hours - * the hours (for molad calculations). It will reject an hour < 0 or > 23 - * @param minutes - * the minutes (for molad calculations). It will reject a minute < 0 or > 59 - * @param chalakim - * the chalakim / parts (for molad calculations). It will reject a chalakim < 0 or > - * 17. 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) - * - * @throws IllegalArgumentException - * if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month < 1 or > 12 (or 13 on a leap year), - * the day of month is < 1 or > 30, an hour < 0 or > 23, a minute < 0 or > 59 or chalakim - * < 0 or > 17. For larger a larger number of chalakim 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). - */ - private static void validateJewishDate(int year, int month, int dayOfMonth, int hours, int minutes, int chalakim) { - if (month < NISSAN || month > getLastMonthOfJewishYear(year)) { - throw new IllegalArgumentException("The Jewish month has to be between 1 and 12 (or 13 on a leap year). " - + month + " is invalid for the year " + year + "."); - } - if (dayOfMonth < 1 || dayOfMonth > 30) { - throw new IllegalArgumentException("The Jewish day of month can't be < 1 or > 30. " + dayOfMonth - + " is invalid."); - } - // reject dates prior to 18 Teves, 3761 (1/1/1 AD). This restriction can be relaxed if the date coding is - // changed/corrected - if ((year < 3761) || (year == 3761 && (month >= TISHREI && month < TEVES)) - || (year == 3761 && month == TEVES && dayOfMonth < 18)) { - throw new IllegalArgumentException( - "A Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian) can't be set. " + year + ", " + month - + ", " + dayOfMonth + " is invalid."); - } - if (hours < 0 || hours > 23) { - throw new IllegalArgumentException("Hours < 0 or > 23 can't be set. " + hours + " is invalid."); - } - - if (minutes < 0 || minutes > 59) { - throw new IllegalArgumentException("Minutes < 0 or > 59 can't be set. " + minutes + " is invalid."); - } - - if (chalakim < 0 || chalakim > 17) { - throw new IllegalArgumentException( - "Chalakim/parts < 0 or > 17 can't be set. " - + chalakim - + " 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)"); - } - } - - /** - * Validates the components of a Gregorian date for validity. It will throw an {@link IllegalArgumentException} if a - * year of < 1, a month < 0 or > 11 or a day of month < 1 is passed in. - * - * @param year - * the Gregorian year to validate. It will reject any year < 1. - * @param month - * the Gregorian month number to validate. It will enforce that the month is between 0 - 11 like a - * {@link GregorianCalendar}, where {@link Calendar#JANUARY} has a value of 0. - * @param dayOfMonth - * the day of the Gregorian month to validate. It will reject any value < 1, but will allow values > 31 - * since calling methods will simply set it to the maximum for that month. TODO: check calling methods to - * see if there is any reason that the class needs days > the maximum. - * @throws IllegalArgumentException - * if a year of < 1, a month < 0 or > 11 or a day of month < 1 is passed in - * @see #validateGregorianYear(int) - * @see #validateGregorianMonth(int) - * @see #validateGregorianDayOfMonth(int) - */ - private static void validateGregorianDate(int year, int month, int dayOfMonth) { - validateGregorianMonth(month); - validateGregorianDayOfMonth(dayOfMonth); - validateGregorianYear(year); - } - - /** - * Validates a Gregorian month for validity. - * - * @param month - * the Gregorian month number to validate. It will enforce that the month is between 0 - 11 like a - * {@link GregorianCalendar}, where {@link Calendar#JANUARY} has a value of 0. - */ - private static void validateGregorianMonth(int month) { - if (month > 11 || month < 0) { - throw new IllegalArgumentException("The Gregorian month has to be between 0 - 11. " + month - + " is invalid."); - } - } - - /** - * Validates a Gregorian day of month for validity. - * - * @param dayOfMonth - * the day of the Gregorian month to validate. It will reject any value < 1, but will allow values > 31 - * since calling methods will simply set it to the maximum for that month. TODO: check calling methods to - * see if there is any reason that the class needs days > the maximum. - */ - private static void validateGregorianDayOfMonth(int dayOfMonth) { - if (dayOfMonth <= 0) { - throw new IllegalArgumentException("The day of month can't be less than 1. " + dayOfMonth + " is invalid."); - } - } - - /** - * Validates a Gregorian year for validity. - * - * @param year - * the Gregorian year to validate. It will reject any year < 1. - */ - private static void validateGregorianYear(int year) { - if (year < 1) { - throw new IllegalArgumentException("Years < 1 can't be calculated. " + year + " is invalid."); - } - } - - /** - * Returns the number of days for a given Jewish year. ND+ER - * - * @param year - * the Jewish year - * @return the number of days for a given Jewish year. - * @see #isCheshvanLong() - * @see #isKislevShort() - */ - public static int getDaysInJewishYear(int year) { - return getJewishCalendarElapsedDays(year + 1) - getJewishCalendarElapsedDays(year); - } - - /** - * Returns the number of days for the current year that the calendar is set to. - * - * @return the number of days for the Object's current Jewish year. - * @see #isCheshvanLong() - * @see #isKislevShort() - * @see #isJewishLeapYear() - */ - public int getDaysInJewishYear() { - return getDaysInJewishYear(getJewishYear()); - } - - /** - * Returns if Cheshvan is long in a given Jewish year. The method name isLong is done since in a Kesidran (ordered) - * year Cheshvan is short. ND+ER - * - * @param year - * the year - * @return true if Cheshvan is long in Jewish year. - * @see #isCheshvanLong() - * @see #getCheshvanKislevKviah() - */ - private static boolean isCheshvanLong(int year) { - return getDaysInJewishYear(year) % 10 == 5; - } - - /** - * Returns if Cheshvan is long (30 days VS 29 days) for the current year that the calendar is set to. The method - * name isLong is done since in a Kesidran (ordered) year Cheshvan is short. - * - * @return true if Cheshvan is long for the current year that the calendar is set to - * @see #isCheshvanLong() - */ - public boolean isCheshvanLong() { - return isCheshvanLong(getJewishYear()); - } - - /** - * Returns if Kislev is short (29 days VS 30 days) in a given Jewish year. The method name isShort is done since in - * a Kesidran (ordered) year Kislev is long. ND+ER - * - * @param year - * the Jewish year - * @return true if Kislev is short for the given Jewish year. - * @see #isKislevShort() - * @see #getCheshvanKislevKviah() - */ - private static boolean isKislevShort(int year) { - return getDaysInJewishYear(year) % 10 == 3; - } - - /** - * Returns if the Kislev is short for the year that this class is set to. The method name isShort is done since in a - * Kesidran (ordered) year Kislev is long. - * - * @return true if Kislev is short for the year that this class is set to - */ - public boolean isKislevShort() { - return isKislevShort(getJewishYear()); - } - - /** - * Returns the Cheshvan and Kislev kviah (whether a Jewish year is short, regular or long). It will return - * {@link #SHELAIMIM} if both cheshvan and kislev are 30 days, {@link #KESIDRAN} if Cheshvan is 29 days and Kislev - * is 30 days and {@link #CHASERIM} if both are 29 days. - * - * @return {@link #SHELAIMIM} if both cheshvan and kislev are 30 days, {@link #KESIDRAN} if Cheshvan is 29 days and - * Kislev is 30 days and {@link #CHASERIM} if both are 29 days. - * @see #isCheshvanLong() - * @see #isKislevShort() - */ - public int getCheshvanKislevKviah() { - if (isCheshvanLong() && !isKislevShort()) { - return SHELAIMIM; - } else if (!isCheshvanLong() && isKislevShort()) { - return CHASERIM; - } else { - return KESIDRAN; - } - } - - /** - * Returns the number of days of a Jewish month for a given month and year. - * - * @param month - * the Jewish month - * @param year - * the Jewish Year - * @return the number of days for a given Jewish month - */ - private static int getDaysInJewishMonth(int month, int year) { - if ((month == IYAR) || (month == TAMMUZ) || (month == ELUL) || ((month == CHESHVAN) && !(isCheshvanLong(year))) - || ((month == KISLEV) && isKislevShort(year)) || (month == TEVES) - || ((month == ADAR) && !(isJewishLeapYear(year))) || (month == ADAR_II)) { - return 29; - } else { - return 30; - } - } - - /** - * Returns the number of days of the Jewish month that the calendar is currently set to. - * - * @return the number of days for the Jewish month that the calendar is currently set to. - */ - public int getDaysInJewishMonth() { - return getDaysInJewishMonth(getJewishMonth(), getJewishYear()); - } - - /** - * Computes the Jewish date from the absolute date. - */ - private void absDateToJewishDate() { - // Approximation from below - jewishYear = (gregorianAbsDate - JEWISH_EPOCH) / 366; - // Search forward for year from the approximation - while (gregorianAbsDate >= jewishDateToAbsDate(jewishYear + 1, TISHREI, 1)) { - jewishYear++; - } - // Search forward for month from either Tishri or Nissan. - if (gregorianAbsDate < jewishDateToAbsDate(jewishYear, NISSAN, 1)) { - jewishMonth = TISHREI;// Start at Tishri - } else { - jewishMonth = NISSAN;// Start at Nissan - } - while (gregorianAbsDate > jewishDateToAbsDate(jewishYear, jewishMonth, getDaysInJewishMonth())) { - jewishMonth++; - } - // Calculate the day by subtraction - jewishDay = gregorianAbsDate - jewishDateToAbsDate(jewishYear, jewishMonth, 1) + 1; - } - - /** - * Returns the absolute date of Jewish date. ND+ER - * - * @param year - * the Jewish year. The year can't be negative - * @param month - * the Jewish month starting with Nissan. Nissan expects a value of 1 etc. until Adar with a value of 12. - * For a leap year, 13 will be the expected value for Adar II. Use the constants {@link JewishDate#NISSAN} - * etc. - * @param dayOfMonth - * the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only - * has 29 days, the day will be set as 29. - * @return the absolute date of the Jewish date. - */ - private static int jewishDateToAbsDate(int year, int month, int dayOfMonth) { - int elapsed = getDaysSinceStartOfJewishYear(year, month, dayOfMonth); - // add elapsed days this year + Days in prior years + Days elapsed before absolute year 1 - return elapsed + getJewishCalendarElapsedDays(year) + JEWISH_EPOCH; - } - - /** - * Returns the molad for a given year and month. Returns a JewishDate {@link Object} set to the date of the molad - * with the {@link #getMoladHours() hours}, {@link #getMoladMinutes() minutes} and {@link #getMoladChalakim() - * chalakim} set. In the current implementation, it sets the molad time based on a midnight date rollover. This - * means that Rosh Chodesh Adar II, 5771 with a molad of 7 chalakim past midnight on Shabbos 29 Adar I / March 5, - * 2011 12:00 AM and 7 chalakim, will have the following values: hours: 0, minutes: 0, Chalakim: 7. - * - * @return a JewishDate {@link Object} set to the date of the molad with the {@link #getMoladHours() hours}, - * {@link #getMoladMinutes() minutes} and {@link #getMoladChalakim() chalakim} set. - */ - public JewishDate getMolad() { - JewishDate moladDate = new JewishDate(getChalakimSinceMoladTohu()); - if (moladDate.getMoladHours() >= 6) { - moladDate.forward(Calendar.DATE, 1); - } - moladDate.setMoladHours((moladDate.getMoladHours() + 18) % 24); - return moladDate; - } - - /** - * Returns the number of days from the Jewish epoch from the number of chalakim from the epoch passed in. - * - * @param chalakim - * the number of chalakim since the beginning of Sunday prior to BaHaRaD - * @return the number of days from the Jewish epoch - */ - private static int moladToAbsDate(long chalakim) { - return (int) (chalakim / CHALAKIM_PER_DAY) + JEWISH_EPOCH; - } - - /** - * Constructor that creates a JewishDate based on a molad passed in. The molad would be the number of - * chalakim / parts starting at the beginning of Sunday prior to the Molad Tohu BeHaRaD (Be = - * Monday, Ha = 5 hours and RaD = 204 chalakim / parts) - prior to the start of the Jewish - * calendar. BeHaRaD is 23:11:20 on Sunday night(5 hours 204/1080 chalakim after sunset on Sunday evening). - * - * @param molad the number of chalakim since the beginning of Sunday prior to BaHaRaD - */ - public JewishDate(long molad) { - absDateToDate(moladToAbsDate(molad)); - int conjunctionDay = (int) (molad / (long) CHALAKIM_PER_DAY); - int conjunctionParts = (int) (molad - conjunctionDay * (long) CHALAKIM_PER_DAY); - setMoladTime(conjunctionParts); - } - - /** - * Sets the molad time (hours minutes and chalakim) based on the number of chalakim since the start of the day. - * - * @param chalakim - * the number of chalakim since the start of the day. - */ - private void setMoladTime(int chalakim) { - int adjustedChalakim = chalakim; - setMoladHours(adjustedChalakim / CHALAKIM_PER_HOUR); - adjustedChalakim = adjustedChalakim - (getMoladHours() * CHALAKIM_PER_HOUR); - setMoladMinutes(adjustedChalakim / CHALAKIM_PER_MINUTE); - setMoladChalakim(adjustedChalakim - moladMinutes * CHALAKIM_PER_MINUTE); - } - - /** - * returns the number of days from Rosh Hashana of the date passed in, to the full date passed in. - * - * @param year - * the Jewish year - * @param month - * the Jewish month - * @param dayOfMonth - * the day in the Jewish month - * @return the number of days - */ - private static int getDaysSinceStartOfJewishYear(int year, int month, int dayOfMonth) { - int elapsedDays = dayOfMonth; - // Before Tishrei (from Nissan to Tishrei), add days in prior months - if (month < TISHREI) { - // this year before and after Nissan. - for (int m = TISHREI; m <= getLastMonthOfJewishYear(year); m++) { - elapsedDays += getDaysInJewishMonth(m, year); - } - for (int m = NISSAN; m < month; m++) { - elapsedDays += getDaysInJewishMonth(m, year); - } - } else { // Add days in prior months this year - for (int m = TISHREI; m < month; m++) { - elapsedDays += getDaysInJewishMonth(m, year); - } - } - return elapsedDays; - } - - /** - * returns the number of days from Rosh Hashana of the date passed in, to the full date passed in. - * - * @return the number of days - */ - public int getDaysSinceStartOfJewishYear() { - return getDaysSinceStartOfJewishYear(getJewishYear(), getJewishMonth(), getJewishDayOfMonth()); - } - - /** - * Creates a Jewish date based on a Jewish year, month and day of month. - * - * @param jewishYear - * the Jewish year - * @param jewishMonth - * the Jewish month. The method expects a 1 for Nissan ... 12 for Adar and 13 for Adar II. Use the - * constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar II) to avoid any - * confusion. - * @param jewishDayOfMonth - * the Jewish day of month. If 30 is passed in for a month with only 29 days (for example {@link #IYAR}, - * or {@link #KISLEV} in a year that {@link #isKislevShort()}), the 29th (last valid date of the month) - * will be set - * @throws IllegalArgumentException - * if the day of month is < 1 or > 30, or a year of < 0 is passed in. - */ - public JewishDate(int jewishYear, int jewishMonth, int jewishDayOfMonth) { - setJewishDate(jewishYear, jewishMonth, jewishDayOfMonth); - } - - /** - * Default constructor will set a default date to the current system date. - */ - public JewishDate() { - resetDate(); - } - - /** - * A constructor that initializes the date to the {@link java.util.Calendar Calendar} parameter. - * - * @param zonedDateTime - * the ZonedDateTime to set the calendar to - * @throws IllegalArgumentException - * if the {@link Calendar#ERA} is {@link GregorianCalendar#BC} - */ - public JewishDate(ZonedDateTime zonedDateTime) { - setGregorianDate(zonedDateTime); - } - - /** - * A constructor that initializes the date to the {@link java.time.LocalDate LocalDate} parameter. - * - * @param localDate - * the LocalDate to set the calendar to - * @throws IllegalArgumentException - * if the {@link Calendar#ERA} is {@link GregorianCalendar#BC} - */ - public JewishDate(LocalDate localDate) { - setGregorianDate(localDate); - } - - /** - * Sets the date based on a {@link java.util.Calendar Calendar} object. Modifies the Jewish date as well. - * - * @param zonedDateTime - * the ZonedDateTime to set the calendar to - * @throws IllegalArgumentException - * if the {@link Calendar#ERA} is {@link GregorianCalendar#BC} - */ - public void setGregorianDate(ZonedDateTime zonedDateTime) { - setGregorianDate(zonedDateTime.toLocalDate()); - } - - /** - * Sets the date based on a {@link java.time.LocalDate LocalDate} object. Modifies the Jewish date as well. - * - * @param localDate - * the LocalDate to set the calendar to - * @throws IllegalArgumentException - * if the date would fall prior to the year 1 AD - */ - public void setGregorianDate(LocalDate localDate) { - if (localDate.getYear() <= 0) { - throw new IllegalArgumentException( - "Calendars with a BC era are not supported. The year " - + localDate.getYear() + " BC is invalid." - ); - } - - gregorianYear = localDate.getYear(); - gregorianMonth = localDate.getMonth().getValue(); // FIXME + 1;// 1 = January - gregorianDayOfMonth = localDate.getDayOfMonth(); - - // initialize absolute date - gregorianAbsDate = gregorianDateToAbsDate(gregorianYear, gregorianMonth, gregorianDayOfMonth); - - // convert to Jewish date - absDateToJewishDate(); - - // day of week (same calculation as original) - dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; - } - - /** - * Sets the Gregorian Date, and updates the Jewish date accordingly. Like the Java Calendar A value of 0 is expected - * for January. - * - * @param year - * the Gregorian year - * @param month - * the Gregorian month. Like the Java Calendar, this class expects 0 for January - * @param dayOfMonth - * the Gregorian day of month. If this is > the number of days in the month/year, the last valid date of - * the month will be set - * @throws IllegalArgumentException - * if a year of < 1, a month < 0 or > 11 or a day of month < 1 is passed in - */ - public void setGregorianDate(int year, int month, int dayOfMonth) { - validateGregorianDate(year, month, dayOfMonth); - setInternalGregorianDate(year, month + 1, dayOfMonth); - } - - /** - * Sets the hidden internal representation of the Gregorian date , and updates the Jewish date accordingly. While - * public getters and setters have 0 based months matching the Java Calendar classes, This class internally - * represents the Gregorian month starting at 1. When this is called it will not adjust the month to match the Java - * Calendar classes. - * - * @param year the year - * @param month the month - * @param dayOfMonth the day of month - */ - private void setInternalGregorianDate(int year, int month, int dayOfMonth) { - // make sure date is a valid date for the given month, if not, set to last day of month - if (dayOfMonth > getLastDayOfGregorianMonth(month, year)) { - dayOfMonth = getLastDayOfGregorianMonth(month, year); - } - // init month, date, year - gregorianMonth = month; - gregorianDayOfMonth = dayOfMonth; - gregorianYear = year; - - gregorianAbsDate = gregorianDateToAbsDate(gregorianYear, gregorianMonth, gregorianDayOfMonth); // init date - absDateToJewishDate(); - - dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // set day of week - } - - /** - * Sets the Jewish Date and updates the Gregorian date accordingly. - * - * @param year - * the Jewish year. The year can't be negative - * @param month - * the Jewish month starting with Nissan. A value of 1 is expected for Nissan ... 12 for Adar and 13 for - * Adar II. Use the constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar - * II) to avoid any confusion. - * @param dayOfMonth - * the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only - * has 29 days, the day will be set as 29. - * @throws IllegalArgumentException - * if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month < 1 or > 12 (or 13 on a - * leap year) or the day of month is < 1 or > 30 is passed in - */ - public void setJewishDate(int year, int month, int dayOfMonth) { - setJewishDate(year, month, dayOfMonth, 0, 0, 0); - } - - /** - * Sets the Jewish Date and updates the Gregorian date accordingly. - * - * @param year - * the Jewish year. The year can't be negative - * @param month - * the Jewish month starting with Nissan. A value of 1 is expected for Nissan ... 12 for Adar and 13 for - * Adar II. Use the constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar - * II) to avoid any confusion. - * @param dayOfMonth - * the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only - * has 29 days, the day will be set as 29. - * - * @param hours - * the hour of the day. Used for molad calculations - * @param minutes - * the minutes. Used for molad calculations - * @param chalakim - * the chalakim / parts. Used for molad calculations. The chalakim should not - * exceed 17. Minutes should be used for larger numbers. - * - * @throws IllegalArgumentException - * if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month < 1 or > 12 (or 13 on a leap year), the day - * of month is < 1 or > 30, an hour < 0 or > 23, a minute < 0 > 59 or chalakim < 0 > 17. For - * larger a larger number of chalakim 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). - */ - public void setJewishDate(int year, int month, int dayOfMonth, int hours, int minutes, int chalakim) { - validateJewishDate(year, month, dayOfMonth, hours, minutes, chalakim); - - // if 30 is passed for a month that only has 29 days (for example by rolling the month from a month that had 30 - // days to a month that only has 29) set the date to 29th - if (dayOfMonth > getDaysInJewishMonth(month, year)) { - dayOfMonth = getDaysInJewishMonth(month, year); - } - - jewishMonth = month; - jewishDay = dayOfMonth; - jewishYear = year; - moladHours = hours; - moladMinutes = minutes; - moladChalakim = chalakim; - - gregorianAbsDate = jewishDateToAbsDate(jewishYear, jewishMonth, jewishDay); // reset Gregorian date - absDateToDate(gregorianAbsDate); - - dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // reset day of week - } - - /** - * Returns this object's date as a {@link java.util.Calendar} object. - * - * @return The {@link java.util.Calendar} - */ - public Calendar getGregorianCalendar() { - Calendar calendar = Calendar.getInstance(); - calendar.set(getGregorianYear(), getGregorianMonth(), getGregorianDayOfMonth()); - return calendar; - } - - /** - * Returns this object's date as a {@link java.time.LocalDate} object. - * - * @return The {@link java.time.LocalDate} - */ - public LocalDate getLocalDate() { - return LocalDate.of(getGregorianYear(), getGregorianMonth() + 1, getGregorianDayOfMonth()); - } - - /** - * Resets this date to the current system date. - */ - public void resetDate() { - LocalDate localDate = LocalDate.now(); - setGregorianDate(localDate); - } - - /** - * Returns a string containing the Jewish date in the form, "day Month, year" e.g. "21 Shevat, 5729". For more - * complex formatting, use the formatter classes. - * - * @return the Jewish date in the form "day Month, year" e.g. "21 Shevat, 5729" - * @see HebrewDateFormatter#format(JewishDate) - */ - public String toString() { - return new HebrewDateFormatter().format(this); - } - - /** - * Rolls the date, month or year forward by the amount passed in. It modifies both the Gregorian and Jewish dates accordingly. - * If manipulation beyond the fields supported here is required, use the {@link Calendar} class {@link Calendar#add(int, int)} - * or {@link Calendar#roll(int, int)} methods in the following manner. - * - *
-	 * 
-	 * 	Calendar cal = jewishDate.getTime(); // get a java.util.Calendar representation of the JewishDate
-	 * 	cal.add(Calendar.MONTH, 3); // add 3 Gregorian months
-	 * 	jewishDate.setDate(cal); // set the updated calendar back to this class
-	 * 
-	 * 
- * - * @param field the calendar field to be forwarded. The must be {@link Calendar#DATE}, {@link Calendar#MONTH} or {@link Calendar#YEAR} - * @param amount the positive amount to move forward - * @throws IllegalArgumentException if the field is anything besides {@link Calendar#DATE}, {@link Calendar#MONTH} or {@link Calendar#YEAR} - * or if the amount is less than 1 - * - * @see #back() - * @see Calendar#add(int, int) - * @see Calendar#roll(int, int) - */ - public void forward(int field, int amount) { //FIXME first param should be converted from the Calendar.DATE - if (field != Calendar.DATE && field != Calendar.MONTH && field != Calendar.YEAR) { - throw new IllegalArgumentException("Unsupported field was passed to Forward. Only Calendar.DATE, Calendar.MONTH or Calendar.YEAR are supported."); - } - if (amount < 1) { - throw new IllegalArgumentException("JewishDate.forward() does not support amounts less than 1. See JewishDate.back()"); - } - if (field == Calendar.DATE) { - // Change Gregorian date - for (int i = 0; i < amount; i++) { - if (gregorianDayOfMonth == getLastDayOfGregorianMonth(gregorianMonth, gregorianYear)) { - gregorianDayOfMonth = 1; - // if last day of year - if (gregorianMonth == 12) { - gregorianYear++; - gregorianMonth = 1; - } else { - gregorianMonth++; - } - } else { // if not last day of month - gregorianDayOfMonth++; - } - - // Change the Jewish Date - if (jewishDay == getDaysInJewishMonth()) { - // if it last day of elul (i.e. last day of Jewish year) - if (jewishMonth == ELUL) { - jewishYear++; - jewishMonth++; - jewishDay = 1; - } else if (jewishMonth == getLastMonthOfJewishYear(jewishYear)) { - // if it is the last day of Adar, or Adar II as case may be - jewishMonth = NISSAN; - jewishDay = 1; - } else { - jewishMonth++; - jewishDay = 1; - } - } else { // if not last date of month - jewishDay++; - } - - if (dayOfWeek == 7) { // if last day of week, loop back to Sunday - dayOfWeek = 1; - } else { - dayOfWeek++; - } - - gregorianAbsDate++; // increment the absolute date - } - } else if (field == Calendar.MONTH) { - forwardJewishMonth(amount); - } else { - setJewishYear(getJewishYear() + amount); - } - } - - /** - * Forward the Jewish date by the number of months passed in. - * 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 - * the way that the Java Calendar behaves (not that simple since there is a difference between add() or roll(). - * - * @throws IllegalArgumentException if the amount is less than 1 - * @param amount the number of months to roll the month forward - */ - private void forwardJewishMonth(int amount) { - if (amount < 1) { - throw new IllegalArgumentException("the amount of months to forward has to be greater than zero."); - } - for (int i = 0; i < amount; i++) { - if (getJewishMonth() == ELUL) { - setJewishMonth(TISHREI); - setJewishYear(getJewishYear() + 1); - } else if ((! isJewishLeapYear() && getJewishMonth() == ADAR) - || (isJewishLeapYear() && getJewishMonth() == ADAR_II)){ - setJewishMonth(NISSAN); - } else { - setJewishMonth(getJewishMonth() + 1); - } - } - } - - /** - * Rolls the date back by 1 day. It modifies both the Gregorian and Jewish dates accordingly. The API does not - * currently offer the ability to forward more than one day at a time, or to forward by month or year. If such - * manipulation is required use the {@link Calendar} class {@link Calendar#add(int, int)} or - * {@link Calendar#roll(int, int)} methods in the following manner. - * - *
-	 * 
-	 * 	Calendar cal = jewishDate.getTime(); // get a java.util.Calendar representation of the JewishDate
-	 * 	cal.add(Calendar.MONTH, -3); // subtract 3 Gregorian months
-	 * 	jewishDate.setDate(cal); // set the updated calendar back to this class
-	 * 
-	 * 
- * - * @see #back() - * @see Calendar#add(int, int) - * @see Calendar#roll(int, int) - */ - public void back() { - // Change Gregorian date - if (gregorianDayOfMonth == 1) { // if first day of month - if (gregorianMonth == 1) { // if first day of year - gregorianMonth = 12; - gregorianYear--; - } else { - gregorianMonth--; - } - // change to last day of previous month - gregorianDayOfMonth = getLastDayOfGregorianMonth(gregorianMonth, gregorianYear); - } else { - gregorianDayOfMonth--; - } - // change Jewish date - if (jewishDay == 1) { // if first day of the Jewish month - if (jewishMonth == NISSAN) { - jewishMonth = getLastMonthOfJewishYear(jewishYear); - } else if (jewishMonth == TISHREI) { // if Rosh Hashana - jewishYear--; - jewishMonth--; - } else { - jewishMonth--; - } - jewishDay = getDaysInJewishMonth(); - } else { - jewishDay--; - } - - if (dayOfWeek == 1) { // if first day of week, loop back to Saturday - dayOfWeek = 7; - } else { - dayOfWeek--; - } - gregorianAbsDate--; // change the absolute date - } - - /** - * Indicates whether some other object is "equal to" this one. - * @see Object#equals(Object) - */ - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (!(object instanceof JewishDate)) { - return false; - } - JewishDate jewishDate = (JewishDate) object; - return gregorianAbsDate == jewishDate.getAbsDate(); - } - - /** - * Compares two dates as per the compareTo() method in the Comparable interface. Returns a value less than 0 if this - * date is "less than" (before) the date, greater than 0 if this date is "greater than" (after) the date, or 0 if - * they are equal. - */ - public int compareTo(JewishDate jewishDate) { - return Integer.compare(gregorianAbsDate, jewishDate.getAbsDate()); - } - - /** - * Returns the Gregorian month (between 0-11). - * - * @return the Gregorian month (between 0-11). Like the java.util.Calendar, months are 0 based. - */ - public int getGregorianMonth() { - return gregorianMonth - 1; //FIXME - } - - /** - * Returns the Gregorian day of the month. - * - * @return the Gregorian day of the mont - */ - public int getGregorianDayOfMonth() { - return gregorianDayOfMonth; - } - - /** - * Returns the Gregorian year. - * - * @return the Gregorian year - */ - public int getGregorianYear() { - return gregorianYear; - } - - /** - * Returns the Jewish month 1-12 (or 13 years in a leap year). The month count starts with 1 for Nissan and goes to - * 13 for Adar II - * - * @return the Jewish month from 1 to 12 (or 13 years in a leap year). The month count starts with 1 for Nissan and - * goes to 13 for Adar II - */ - public int getJewishMonth() { - return jewishMonth; - } - - /** - * Returns the Jewish day of month. - * - * @return the Jewish day of the month - */ - public int getJewishDayOfMonth() { - return jewishDay; - } - - /** - * Returns the Jewish year. - * - * @return the Jewish year - */ - public int getJewishYear() { - return jewishYear; - } - - /** - * Returns the day of the week as a number between 1-7. - * - * @return the day of the week as a number between 1-7. - */ - public int getDayOfWeek() { - return dayOfWeek; - } - - /** - * Sets the Gregorian month. - * - * @param month - * the Gregorian month - * - * @throws IllegalArgumentException - * if a month < 0 or > 11 is passed in - */ - public void setGregorianMonth(int month) { - validateGregorianMonth(month); - setInternalGregorianDate(gregorianYear, month + 1, gregorianDayOfMonth); //FIXME - } - - /** - * sets the Gregorian year. - * - * @param year - * the Gregorian year. - * @throws IllegalArgumentException - * if a year of < 1 is passed in - */ - public void setGregorianYear(int year) { - validateGregorianYear(year); - setInternalGregorianDate(year, gregorianMonth, gregorianDayOfMonth); - } - - /** - * sets the Gregorian Day of month. - * - * @param dayOfMonth - * the Gregorian Day of month. - * @throws IllegalArgumentException - * if the day of month of < 1 is passed in - */ - public void setGregorianDayOfMonth(int dayOfMonth) { - validateGregorianDayOfMonth(dayOfMonth); - setInternalGregorianDate(gregorianYear, gregorianMonth, dayOfMonth); - } - - /** - * sets the Jewish month. - * - * @param month - * the Jewish month from 1 to 12 (or 13 years in a leap year). The month count starts with 1 for Nissan - * and goes to 13 for Adar II - * @throws IllegalArgumentException - * if a month < 1 or > 12 (or 13 on a leap year) is passed in - */ - public void setJewishMonth(int month) { - setJewishDate(jewishYear, month, jewishDay); - } - - /** - * sets the Jewish year. - * - * @param year - * the Jewish year - * @throws IllegalArgumentException - * if a year of < 3761 is passed in. The same will happen if the year is 3761 and the month and day - * previously set are < 18 Teves (prior to Jan 1, 1 AD) - */ - public void setJewishYear(int year) { - setJewishDate(year, jewishMonth, jewishDay); - } - - /** - * sets the Jewish day of month. - * - * @param dayOfMonth - * the Jewish day of month - * @throws IllegalArgumentException - * if the day of month is < 1 or > 30 is passed in - */ - public void setJewishDayOfMonth(int dayOfMonth) { - setJewishDate(jewishYear, jewishMonth, dayOfMonth); - } - - /** - * A method that creates a deep copy of the object. - * - * @see Object#clone() - */ - public Object clone() { - JewishDate clone = null; - try { - clone = (JewishDate) super.clone(); - } catch (CloneNotSupportedException cnse) { - // Required by the compiler. Should never be reached since we implement clone() - } - if (clone != null) { - clone.setInternalGregorianDate(gregorianYear, gregorianMonth, gregorianDayOfMonth); - } - return clone; - } - - /** - * Overrides {@link Object#hashCode()}. - * @see Object#hashCode() - */ - public int hashCode() { - int result = 17; - result = 37 * result + getClass().hashCode(); // needed or this and subclasses will return identical hash - result += 37 * result + gregorianAbsDate; - return result; - } + /** + * Value of the month field indicating Nissan, the first numeric month of the year in the Jewish calendar. With the + * year starting at {@link #TISHREI}, it would actually be the 7th (or 8th in a {@link #isJewishLeapYear() leap + * year}) month of the year. + */ + public static final int NISSAN = 1; + + /** + * Value of the month field indicating Iyar, the second numeric month of the year in the Jewish calendar. With the + * year starting at {@link #TISHREI}, it would actually be the 8th (or 9th in a {@link #isJewishLeapYear() leap + * year}) month of the year. + */ + public static final int IYAR = 2; + + /** + * Value of the month field indicating Sivan, the third numeric month of the year in the Jewish calendar. With the + * year starting at {@link #TISHREI}, it would actually be the 9th (or 10th in a {@link #isJewishLeapYear() leap + * year}) month of the year. + */ + public static final int SIVAN = 3; + + /** + * Value of the month field indicating Tammuz, the fourth numeric month of the year in the Jewish calendar. With the + * year starting at {@link #TISHREI}, it would actually be the 10th (or 11th in a {@link #isJewishLeapYear() leap + * year}) month of the year. + */ + public static final int TAMMUZ = 4; + + /** + * Value of the month field indicating Av, the fifth numeric month of the year in the Jewish calendar. With the year + * starting at {@link #TISHREI}, it would actually be the 11th (or 12th in a {@link #isJewishLeapYear() leap year}) + * month of the year. + */ + public static final int AV = 5; + + /** + * Value of the month field indicating Elul, the sixth numeric month of the year in the Jewish calendar. With the + * year starting at {@link #TISHREI}, it would actually be the 12th (or 13th in a {@link #isJewishLeapYear() leap + * year}) month of the year. + */ + public static final int ELUL = 6; + + /** + * Value of the month field indicating Tishrei, the seventh numeric month of the year in the Jewish calendar. With + * the year starting at this month, it would actually be the 1st month of the year. + */ + public static final int TISHREI = 7; + + /** + * Value of the month field indicating Cheshvan/marcheshvan, the eighth numeric month of the year in the Jewish + * calendar. With the year starting at {@link #TISHREI}, it would actually be the 2nd month of the year. + */ + public static final int CHESHVAN = 8; + + /** + * Value of the month field indicating Kislev, the ninth numeric month of the year in the Jewish calendar. With the + * year starting at {@link #TISHREI}, it would actually be the 3rd month of the year. + */ + public static final int KISLEV = 9; + + /** + * Value of the month field indicating Teves, the tenth numeric month of the year in the Jewish calendar. With the + * year starting at {@link #TISHREI}, it would actually be the 4th month of the year. + */ + public static final int TEVES = 10; + + /** + * Value of the month field indicating Shevat, the eleventh numeric month of the year in the Jewish calendar. With + * the year starting at {@link #TISHREI}, it would actually be the 5th month of the year. + */ + public static final int SHEVAT = 11; + + /** + * Value of the month field indicating Adar (or Adar I in a {@link #isJewishLeapYear() leap year}), the twelfth + * numeric month of the year in the Jewish calendar. With the year starting at {@link #TISHREI}, it would actually + * be the 6th month of the year. + */ + public static final int ADAR = 12; + + /** + * Value of the month field indicating Adar II, the leap (intercalary or embolismic) thirteenth (Undecimber) numeric + * month of the year added in Jewish {@link #isJewishLeapYear() leap year}). The leap years are years 3, 6, 8, 11, + * 14, 17 and 19 of a 19-year cycle. With the year starting at {@link #TISHREI}, it would actually be the 7th month + * of the year. + */ + public static final int ADAR_II = 13; + + /** + * the Jewish epoch using the RD (Rata Die/Fixed Date or Reingold Dershowitz) day used in Calendrical Calculations. + * Day 1 is January 1, 0001 of the Gregorian calendar + */ + private static final int JEWISH_EPOCH = -1373429; + + /** The number of chalakim (18) in a minute.*/ + private static final int CHALAKIM_PER_MINUTE = 18; + /** The number of chalakim (1080) in an hour.*/ + private static final int CHALAKIM_PER_HOUR = 1080; + /** The number of chalakim (25,920) in a 24-hour day .*/ + private static final int CHALAKIM_PER_DAY = 25920; // 24 * 1080 + /** The number of chalakim in an average Jewish month. A month has 29 days, 12 hours and 793 + * chalakim (44 minutes and 3.3 seconds) for a total of 765,433 chalakim*/ + private static final long CHALAKIM_PER_MONTH = 765433; // (29 * 24 + 12) * 1080 + 793 + /** + * Days from the beginning of Sunday till molad BaHaRaD. Calculated as 1 day, 5 hours and 204 chalakim = + * (24 + 5) * 1080 + 204 = 31524 + */ + private static final int CHALAKIM_MOLAD_TOHU = 31524; + + /** + * A short year where both {@link #CHESHVAN} and {@link #KISLEV} are 29 days. + * + * @see #getCheshvanKislevKviah() + * @see HebrewDateFormatter#getFormattedKviah(int) + */ + public static final int CHASERIM = 0; + + /** + * An ordered year where {@link #CHESHVAN} is 29 days and {@link #KISLEV} is 30 days. + * + * @see #getCheshvanKislevKviah() + * @see HebrewDateFormatter#getFormattedKviah(int) + */ + public static final int KESIDRAN = 1; + + /** + * A long year where both {@link #CHESHVAN} and {@link #KISLEV} are 30 days. + * + * @see #getCheshvanKislevKviah() + * @see HebrewDateFormatter#getFormattedKviah(int) + */ + public static final int SHELAIMIM = 2; + + /** the internal Jewish month.*/ + private int jewishMonth; + /** the internal Jewish day.*/ + private int jewishDay; + /** the internal Jewish year.*/ + private int jewishYear; + /** the internal count of molad hours.*/ + private int moladHours; + /** the internal count of molad minutes.*/ + private int moladMinutes; + /** the internal count of molad chalakim.*/ + private int moladChalakim; + + /** + * Returns the molad hours. Only a JewishDate object populated with {@link #getMolad()}, + * {@link #setJewishDate(int, int, int, int, int, int)} or {@link #setMoladHours(int)} will have this field + * populated. A regular JewishDate object will have this field set to 0. + * + * @return the molad hours + * @see #setMoladHours(int) + * @see #getMolad() + * @see #setJewishDate(int, int, int, int, int, int) + */ + public int getMoladHours() { + return moladHours; + } + + /** + * Sets the molad hours. + * + * @param moladHours + * the molad hours to set + * @see #getMoladHours() + * @see #getMolad() + * @see #setJewishDate(int, int, int, int, int, int) + * + */ + public void setMoladHours(int moladHours) { + this.moladHours = moladHours; + } + + /** + * Returns the molad minutes. Only an object populated with {@link #getMolad()}, + * {@link #setJewishDate(int, int, int, int, int, int)} or or {@link #setMoladMinutes(int)} will have these fields + * populated. A regular JewishDate object will have this field set to 0. + * + * @return the molad minutes + * @see #setMoladMinutes(int) + * @see #getMolad() + * @see #setJewishDate(int, int, int, int, int, int) + */ + public int getMoladMinutes() { + return moladMinutes; + } + + /** + * Sets the molad minutes. The expectation is that the traditional minute-less chalakim will be broken out to + * minutes and {@link #setMoladChalakim(int) chalakim / parts} , so 793 (TaShTZaG) parts would have the minutes set to + * 44 and chalakim to 1. + * + * @param moladMinutes + * the molad minutes to set + * @see #getMoladMinutes() + * @see #setMoladChalakim(int) + * @see #getMolad() + * @see #setJewishDate(int, int, int, int, int, int) + * + */ + public void setMoladMinutes(int moladMinutes) { + this.moladMinutes = moladMinutes; + } + + /** + * Sets the molad chalakim/parts. The expectation is that the traditional minute-less chalakim will be broken + * out to {@link #setMoladMinutes(int) minutes} and chalakim, so 793 (TaShTZaG) parts would have the minutes set to 44 and + * chalakim to 1. + * + * @param moladChalakim + * the molad chalakim / parts to set + * @see #getMoladChalakim() + * @see #setMoladMinutes(int) + * @see #getMolad() + * @see #setJewishDate(int, int, int, int, int, int) + * + */ + public void setMoladChalakim(int moladChalakim) { + this.moladChalakim = moladChalakim; + } + + /** + * Returns the molad chalakim / parts. Only an object populated with {@link #getMolad()}, + * {@link #setJewishDate(int, int, int, int, int, int)} or or {@link #setMoladChalakim(int)} will have these fields + * populated. A regular JewishDate object will have this field set to 0. + * + * @return the molad chalakim / parts + * @see #setMoladChalakim(int) + * @see #getMolad() + * @see #setJewishDate(int, int, int, int, int, int) + */ + public int getMoladChalakim() { + return moladChalakim; + } + + /** 1 == Sunday, 2 == Monday, etc... */ + private int dayOfWeek; + + /** Returns the absolute date (days since January 1, 0001 of the Gregorian calendar). + * @see #getAbsDate() + * @see #setJewishDateFromAbsDate() + */ + private int gregorianAbsDate; + + /** + * Returns the number of days in a given month in a given month and year. + * + * @param month + * the month. As with other cases in this class, this is 1-based, not zero-based. + * @param year + * the year (only impacts February) + * @return the number of days in the month in the given year + */ + private static int getLastDayOfGregorianMonth(int month, int year) { + return YearMonth.of(year, month).lengthOfMonth(); + } + + /** + * Computes the Gregorian date from the absolute date. ND+ER + * @param absDate the absolute date + */ + private static LocalDate absDateToDate(int absDate) { + int year = absDate / 366; // Search forward year by year from approximate year + while (absDate >= gregorianDateToAbsDate(year + 1, 1, 1)) { + year++; + } + + int month = 1; // Search forward month by month from January + while (absDate > gregorianDateToAbsDate(year, month, getLastDayOfGregorianMonth(month, year))) { + month++; + } + + int dayOfMonth = absDate - gregorianDateToAbsDate(year, month, 1) + 1; + return LocalDate.of(year, month, dayOfMonth); + } + + /** + * Returns the absolute date (days since January 1, 0001 of the Gregorian calendar). + * + * @return the number of days since January 1, 1 + */ + public int getAbsDate() { + return gregorianAbsDate; + } + + /** + * Computes the absolute date from a Gregorian date. ND+ER + * + * @param year + * the Gregorian year + * @param month + * the Gregorian month. Unlike the Java Calendar where January has the value of 0,This expects a 1 for + * January + * @param dayOfMonth + * the day of the month (1st, 2nd, etc...) + * @return the absolute Gregorian day + */ + private static int gregorianDateToAbsDate(int year, int month, int dayOfMonth) { + int absDate = dayOfMonth; + for (int m = month - 1; m > 0; m--) { + absDate += getLastDayOfGregorianMonth(m, year); // days in prior months of the year + } + return (absDate // days this year + + 365 * (year - 1) // days in previous years ignoring leap days + + (year - 1) / 4 // Julian leap days before this year + - (year - 1) / 100 // minus prior century years + + (year - 1) / 400); // plus prior years divisible by 400 + } + + /** + * 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. + * + * @param year + * the Jewish year. + * @return true if it is a leap year + * @see #isJewishLeapYear() + */ + private static boolean isJewishLeapYear(int year) { + return ((7 * year) + 1) % 19 < 7; + } + + /** + * 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 + * cycle are leap years. + * + * @return true if it is a leap year + * @see #isJewishLeapYear(int) + */ + public boolean isJewishLeapYear() { + return isJewishLeapYear(getJewishYear()); + } + + /** + * Returns the last month of a given Jewish year. This will be 12 on a non {@link #isJewishLeapYear(int) leap year} + * or 13 on a leap year. + * + * @param year + * the Jewish year. + * @return 12 on a non leap year or 13 on a leap year + * @see #isJewishLeapYear(int) + */ + private static int getLastMonthOfJewishYear(int year) { + return isJewishLeapYear(year) ? ADAR_II : ADAR; + } + + /** + * Returns the number of days elapsed from the Sunday prior to the start of the Jewish calendar to the mean + * conjunction of Tishri of the Jewish year. + * + * @param year + * the Jewish year + * @return the number of days elapsed from prior to the molad Tohu BaHaRaD (Be = Monday, Ha = 5 + * hours and RaD = 204 chalakim / parts) prior to the start of the Jewish calendar, to + * the mean conjunction of Tishri of the Jewish year. BeHaRaD is 23:11:20 on Sunday night(5 hours 204/1080 + * chalakim after sunset on Sunday evening). + */ + public static int getJewishCalendarElapsedDays(int year) { + long chalakimSince = getChalakimSinceMoladTohu(year, TISHREI); + int moladDay = (int) (chalakimSince / (long) CHALAKIM_PER_DAY); + int moladParts = (int) (chalakimSince - moladDay * (long) CHALAKIM_PER_DAY); + // delay Rosh Hashana for the 4 dechiyos + return addDechiyos(year, moladDay, moladParts); + } + + /** + * Adds the 4 dechiyos for molad Tishrei. These are: + *
    + *
  1. Lo ADU Rosh - Rosh Hashana can't fall on a Sunday, Wednesday or Friday. If the molad fell on one + * of these days, Rosh Hashana is delayed to the following day.
  2. + *
  3. Molad Zaken - If the molad of Tishrei falls after 12 noon, Rosh Hashana is delayed to the following + * day. If the following day is ADU, it will be delayed an additional day.
  4. + *
  5. GaTRaD - If on a non leap year the molad of Tishrei falls on a Tuesday (Ga) on or after 9 hours + * (T) and (RaD 204 chalakim it is delayed till Thursday (one day delay, plus one day for + * Lo ADU Rosh)
  6. + *
  7. BeTuTaKPaT - if the year following a leap year falls on a Monday (Be) on or after 15 hours + * (Tu) and 589 chalakim (TaKPaT) it is delayed till Tuesday
  8. + *
+ * + * @param year the year + * @param moladDay the molad day + * @param moladParts the molad parts + * @return the number of elapsed days in the JewishCalendar adjusted for the 4 dechiyos. + */ + private static int addDechiyos(int year, int moladDay, int moladParts) { + int roshHashanaDay = moladDay; // if no dechiyos + // delay Rosh Hashana for the dechiyos of the Molad - new moon 1 - Molad Zaken, 2- GaTRaD 3- BeTuTaKPaT + if ((moladParts >= 19440) // Dechiya of Molad Zaken - molad is >= midday (18 hours * 1080 chalakim) + || (((moladDay % 7) == 2) // start Dechiya of GaTRaD - Ga = is a Tuesday + && (moladParts >= 9924) // TRaD = 9 hours, 204 parts or later (9 * 1080 + 204) + && !isJewishLeapYear(year)) // of a non-leap year - end Dechiya of GaTRaD + || (((moladDay % 7) == 1) // start Dechiya of BeTuTaKPaT - Be = is on a Monday + && (moladParts >= 16789) // TUTaKPaT part of BeTuTaKPaT = 15 hours, 589 parts or later (15 * 1080 + 589) + && (isJewishLeapYear(year - 1)))) { // in a year following a leap year - end Dechiya of BeTuTaKPaT + roshHashanaDay += 1; // Then postpone Rosh HaShanah one day + } + // start 4th Dechiya - Lo ADU Rosh - Rosh Hashana can't occur on A- sunday, D- Wednesday, U - Friday + if (((roshHashanaDay % 7) == 0)// If Rosh HaShanah would occur on Sunday, + || ((roshHashanaDay % 7) == 3) // or Wednesday, + || ((roshHashanaDay % 7) == 5)) { // or Friday - end 4th Dechiya - Lo ADU Rosh + roshHashanaDay = roshHashanaDay + 1; // Then postpone it one (more) day + } + return roshHashanaDay; + } + + /** + * Returns the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu + * to the year and month passed in. + * + * @param year + * the Jewish year + * @param month + * the Jewish month the Jewish month, with the month numbers starting from Nissan. Use the JewishDate + * constants such as {@link JewishDate#TISHREI}. + * @return the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu + */ + private static long getChalakimSinceMoladTohu(int year, int month) { + // Jewish lunar month = 29 days, 12 hours and 793 chalakim + // chalakim since Molad Tohu BeHaRaD - 1 day, 5 hours and 204 chalakim + int monthOfYear = getJewishMonthOfYear(year, month); + int monthsElapsed = (235 * ((year - 1) / 19)) // Months in complete 19-year lunar (Metonic) cycles so far + + (12 * ((year - 1) % 19)) // Regular months in this cycle + + ((7 * ((year - 1) % 19) + 1) / 19) // Leap months this cycle + + (monthOfYear - 1); // add elapsed months till the start of the molad of the month + // return chalakim prior to BeHaRaD + number of chalakim since + return CHALAKIM_MOLAD_TOHU + (CHALAKIM_PER_MONTH * monthsElapsed); + } + + /** + * Returns the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu + * to the Jewish year and month that this Object is set to. + * + * @return the number of chalakim (parts - 1080 to the hour) from the original hypothetical Molad Tohu + */ + public long getChalakimSinceMoladTohu() { + return getChalakimSinceMoladTohu(jewishYear, jewishMonth); + } + + /** + * Converts the {@link JewishDate#NISSAN} based constants used by this class to numeric month starting from + * {@link JewishDate#TISHREI}. This is required for molad calculations. + * + * @param year + * The Jewish year + * @param month + * The Jewish Month + * @return the Jewish month of the year starting with Tishrei + */ + private static int getJewishMonthOfYear(int year, int month) { + boolean isLeapYear = isJewishLeapYear(year); + return (month + (isLeapYear ? 6 : 5)) % (isLeapYear ? 13 : 12) + 1; + } + + /** + * Validates the components of a Jewish date for validity. It will throw an {@link IllegalArgumentException} if the Jewish + * date is earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month < 1 or > 12 (or 13 on a {@link #isJewishLeapYear(int) + * leap year}), the day of month is < 1 or > 30, an hour < 0 or > 23, a minute < 0 or > 59 or + * chalakim < 0 or > 17. For larger a larger number of chalakim 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). + * + * @param year + * the Jewish year to validate. It will reject any year <= 3761 (lower than the year 1 Gregorian). + * @param month + * the Jewish month to validate. It will reject a month < 1 or > 12 (or 13 on a leap year) . + * @param dayOfMonth + * the day of the Jewish month to validate. It will reject any value < 1 or > 30 TODO: check calling + * methods to see if there is any reason that the class can validate that 30 is invalid for some months. + * @param hours + * the hours (for molad calculations). It will reject an hour < 0 or > 23 + * @param minutes + * the minutes (for molad calculations). It will reject a minute < 0 or > 59 + * @param chalakim + * the chalakim / parts (for molad calculations). It will reject a chalakim < 0 or > + * 17. 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) + * + * @throws IllegalArgumentException + * if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month < 1 or > 12 (or 13 on a leap year), + * the day of month is < 1 or > 30, an hour < 0 or > 23, a minute < 0 or > 59 or chalakim + * < 0 or > 17. For larger a larger number of chalakim 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). + */ + private static void validateJewishDate(int year, int month, int dayOfMonth, int hours, int minutes, int chalakim) { + if (month < NISSAN || month > getLastMonthOfJewishYear(year)) { + throw new IllegalArgumentException("The Jewish month has to be between 1 and 12 (or 13 on a leap year). " + + month + " is invalid for the year " + year + "."); + } + int monthLength = getDaysInJewishMonth(month, year); + if (dayOfMonth < 1 || dayOfMonth > monthLength) { + throw new IllegalArgumentException( + "The Jewish day of month can't be < 1 or > " + monthLength + + " for the month index " + monthLength + ". " + dayOfMonth + " is invalid."); + } + // reject dates prior to 18 Teves, 3761 (1/1/1 AD). This restriction can be relaxed if the date coding is + // changed/corrected + if ((year < 3761) || (year == 3761 && (month >= TISHREI && month < TEVES)) + || (year == 3761 && month == TEVES && dayOfMonth < 18)) { + throw new IllegalArgumentException( + "A Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian) can't be set. " + year + ", " + month + + ", " + dayOfMonth + " is invalid."); + } + if (hours < 0 || hours > 23) { + throw new IllegalArgumentException("Hours < 0 or > 23 can't be set. " + hours + " is invalid."); + } + + if (minutes < 0 || minutes > 59) { + throw new IllegalArgumentException("Minutes < 0 or > 59 can't be set. " + minutes + " is invalid."); + } + + if (chalakim < 0 || chalakim > 17) { + throw new IllegalArgumentException( + "Chalakim/parts < 0 or > 17 can't be set. " + + chalakim + + " 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)"); + } + } + + /** + * Returns the number of days for a given Jewish year. ND+ER + * + * @param year + * the Jewish year + * @return the number of days for a given Jewish year. + * @see #isCheshvanLong() + * @see #isKislevShort() + */ + public static int getDaysInJewishYear(int year) { + return getJewishCalendarElapsedDays(year + 1) - getJewishCalendarElapsedDays(year); + } + + /** + * Returns the number of days for the current year that the calendar is set to. + * + * @return the number of days for the Object's current Jewish year. + * @see #isCheshvanLong() + * @see #isKislevShort() + * @see #isJewishLeapYear() + */ + public int getDaysInJewishYear() { + return getDaysInJewishYear(getJewishYear()); + } + + /** + * Returns if Cheshvan is long in a given Jewish year. The method name isLong is done since in a Kesidran (ordered) + * year Cheshvan is short. ND+ER + * + * @param year + * the year + * @return true if Cheshvan is long in Jewish year. + * @see #isCheshvanLong() + * @see #getCheshvanKislevKviah() + */ + private static boolean isCheshvanLong(int year) { + return getDaysInJewishYear(year) % 10 == 5; + } + + /** + * Returns if Cheshvan is long (30 days VS 29 days) for the current year that the calendar is set to. The method + * name isLong is done since in a Kesidran (ordered) year Cheshvan is short. + * + * @return true if Cheshvan is long for the current year that the calendar is set to + * @see #isCheshvanLong() + */ + public boolean isCheshvanLong() { + return isCheshvanLong(getJewishYear()); + } + + /** + * Returns if Kislev is short (29 days VS 30 days) in a given Jewish year. The method name isShort is done since in + * a Kesidran (ordered) year Kislev is long. ND+ER + * + * @param year + * the Jewish year + * @return true if Kislev is short for the given Jewish year. + * @see #isKislevShort() + * @see #getCheshvanKislevKviah() + */ + private static boolean isKislevShort(int year) { + return getDaysInJewishYear(year) % 10 == 3; + } + + /** + * Returns if the Kislev is short for the year that this class is set to. The method name isShort is done since in a + * Kesidran (ordered) year Kislev is long. + * + * @return true if Kislev is short for the year that this class is set to + */ + public boolean isKislevShort() { + return isKislevShort(getJewishYear()); + } + + /** + * Returns the Cheshvan and Kislev kviah (whether a Jewish year is short, regular or long). It will return + * {@link #SHELAIMIM} if both cheshvan and kislev are 30 days, {@link #KESIDRAN} if Cheshvan is 29 days and Kislev + * is 30 days and {@link #CHASERIM} if both are 29 days. + * + * @return {@link #SHELAIMIM} if both cheshvan and kislev are 30 days, {@link #KESIDRAN} if Cheshvan is 29 days and + * Kislev is 30 days and {@link #CHASERIM} if both are 29 days. + * @see #isCheshvanLong() + * @see #isKislevShort() + */ + public int getCheshvanKislevKviah() { + if (isCheshvanLong() && !isKislevShort()) { + return SHELAIMIM; + } else if (!isCheshvanLong() && isKislevShort()) { + return CHASERIM; + } else { + return KESIDRAN; + } + } + + /** + * Returns the number of days of a Jewish month for a given month and year. + * + * @param month + * the Jewish month + * @param year + * the Jewish Year + * @return the number of days for a given Jewish month + */ + private static int getDaysInJewishMonth(int month, int year) { + if ((month == IYAR) || (month == TAMMUZ) || (month == ELUL) || ((month == CHESHVAN) && !(isCheshvanLong(year))) + || ((month == KISLEV) && isKislevShort(year)) || (month == TEVES) + || ((month == ADAR) && !(isJewishLeapYear(year))) || (month == ADAR_II)) { + return 29; + } else { + return 30; + } + } + + /** + * Returns the number of days of the Jewish month that the calendar is currently set to. + * + * @return the number of days for the Jewish month that the calendar is currently set to. + */ + public int getDaysInJewishMonth() { + return getDaysInJewishMonth(getJewishMonth(), getJewishYear()); + } + + /** + * Computes and sets the Jewish date fields based on the provided absolute (Gregorian) date. + */ + private void setAbsDate(int gregorianAbsDate) { + if (gregorianAbsDate <= 0) { + throw new IllegalArgumentException("Dates in the BC era are not supported"); + } + this.gregorianAbsDate = gregorianAbsDate; + // Approximation from below + jewishYear = (gregorianAbsDate - JEWISH_EPOCH) / 366; + // Search forward for year from the approximation + while (gregorianAbsDate >= jewishDateToAbsDate(jewishYear + 1, TISHREI, 1)) { + jewishYear++; + } + // Search forward for month from either Tishri or Nissan. + if (gregorianAbsDate < jewishDateToAbsDate(jewishYear, NISSAN, 1)) { + jewishMonth = TISHREI;// Start at Tishri + } else { + jewishMonth = NISSAN;// Start at Nissan + } + while (gregorianAbsDate > jewishDateToAbsDate(jewishYear, jewishMonth, getDaysInJewishMonth())) { + jewishMonth++; + } + // Calculate the day by subtraction + jewishDay = gregorianAbsDate - jewishDateToAbsDate(jewishYear, jewishMonth, 1) + 1; + + // day of week (same calculation as original) + dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; + } + + /** + * Returns the absolute date of Jewish date. ND+ER + * + * @param year + * the Jewish year. The year can't be negative + * @param month + * the Jewish month starting with Nissan. Nissan expects a value of 1 etc. until Adar with a value of 12. + * For a leap year, 13 will be the expected value for Adar II. Use the constants {@link JewishDate#NISSAN} + * etc. + * @param dayOfMonth + * the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only + * has 29 days, the day will be set as 29. + * @return the absolute date of the Jewish date. + */ + private static int jewishDateToAbsDate(int year, int month, int dayOfMonth) { + int elapsed = getDaysSinceStartOfJewishYear(year, month, dayOfMonth); + // add elapsed days this year + Days in prior years + Days elapsed before absolute year 1 + return elapsed + getJewishCalendarElapsedDays(year) + JEWISH_EPOCH; + } + + /** + * Returns the molad for a given year and month. Returns a JewishDate {@link Object} set to the date of the molad + * with the {@link #getMoladHours() hours}, {@link #getMoladMinutes() minutes} and {@link #getMoladChalakim() + * chalakim} set. In the current implementation, it sets the molad time based on a midnight date rollover. This + * means that Rosh Chodesh Adar II, 5771 with a molad of 7 chalakim past midnight on Shabbos 29 Adar I / March 5, + * 2011 12:00 AM and 7 chalakim, will have the following values: hours: 0, minutes: 0, Chalakim: 7. + * + * @return a JewishDate {@link Object} set to the date of the molad with the {@link #getMoladHours() hours}, + * {@link #getMoladMinutes() minutes} and {@link #getMoladChalakim() chalakim} set. + */ + public JewishDate getMolad() { + JewishDate moladDate = new JewishDate(getChalakimSinceMoladTohu()); + if (moladDate.getMoladHours() >= 6) { + moladDate.addDays(1); + } + moladDate.setMoladHours((moladDate.getMoladHours() + 18) % 24); + return moladDate; + } + + /** + * Returns the number of days from the Jewish epoch from the number of chalakim from the epoch passed in. + * + * @param chalakim + * the number of chalakim since the beginning of Sunday prior to BaHaRaD + * @return the number of days from the Jewish epoch + */ + private static int moladToAbsDate(long chalakim) { + return (int) (chalakim / CHALAKIM_PER_DAY) + JEWISH_EPOCH; + } + + /** + * Constructor that creates a JewishDate based on a molad passed in. The molad would be the number of + * chalakim / parts starting at the beginning of Sunday prior to the Molad Tohu BeHaRaD (Be = + * Monday, Ha = 5 hours and RaD = 204 chalakim / parts) - prior to the start of the Jewish + * calendar. BeHaRaD is 23:11:20 on Sunday night(5 hours 204/1080 chalakim after sunset on Sunday evening). + * + * @param molad the number of chalakim since the beginning of Sunday prior to BaHaRaD + */ + public JewishDate(long molad) { + setAbsDate(moladToAbsDate(molad)); + int conjunctionDay = (int) (molad / (long) CHALAKIM_PER_DAY); + int chalakim = (int) (molad - conjunctionDay * (long) CHALAKIM_PER_DAY); + setMoladHours(chalakim / CHALAKIM_PER_HOUR); + chalakim = chalakim - (getMoladHours() * CHALAKIM_PER_HOUR); + setMoladMinutes(chalakim / CHALAKIM_PER_MINUTE); + setMoladChalakim(chalakim - moladMinutes * CHALAKIM_PER_MINUTE); + } + + /** + * returns the number of days from Rosh Hashana of the date passed in, to the full date passed in. + * + * @param year + * the Jewish year + * @param month + * the Jewish month + * @param dayOfMonth + * the day in the Jewish month + * @return the number of days + */ + private static int getDaysSinceStartOfJewishYear(int year, int month, int dayOfMonth) { + int elapsedDays = dayOfMonth; + // Before Tishrei (from Nissan to Tishrei), add days in prior months + if (month < TISHREI) { + // this year before and after Nissan. + for (int m = TISHREI; m <= getLastMonthOfJewishYear(year); m++) { + elapsedDays += getDaysInJewishMonth(m, year); + } + for (int m = NISSAN; m < month; m++) { + elapsedDays += getDaysInJewishMonth(m, year); + } + } else { // Add days in prior months this year + for (int m = TISHREI; m < month; m++) { + elapsedDays += getDaysInJewishMonth(m, year); + } + } + return elapsedDays; + } + + /** + * returns the number of days from Rosh Hashana of the date passed in, to the full date passed in. + * + * @return the number of days + */ + public int getDaysSinceStartOfJewishYear() { + return getDaysSinceStartOfJewishYear(getJewishYear(), getJewishMonth(), getJewishDayOfMonth()); + } + + /** + * Creates a Jewish date based on a Jewish year, month and day of month. + * + * @param jewishYear + * the Jewish year + * @param jewishMonth + * the Jewish month. The method expects a 1 for Nissan ... 12 for Adar and 13 for Adar II. Use the + * constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar II) to avoid any + * confusion. + * @param jewishDayOfMonth + * the Jewish day of month. If 30 is passed in for a month with only 29 days (for example {@link #IYAR}, + * or {@link #KISLEV} in a year that {@link #isKislevShort()}), the 29th (last valid date of the month) + * will be set + * @throws IllegalArgumentException + * if the day of month is < 1 or > 30, or a year of < 0 is passed in. + */ + public JewishDate(int jewishYear, int jewishMonth, int jewishDayOfMonth) { + setJewishDate(jewishYear, jewishMonth, jewishDayOfMonth); + } + + /** + * Default constructor will set a default date to the current system date. + */ + public JewishDate() { + resetDate(); + } + + /** + * A constructor that initializes the date to the {@link java.util.Calendar Calendar} parameter. + * + * @param zonedDateTime + * the ZonedDateTime to set the calendar to + * @throws IllegalArgumentException + * if the {@link Calendar#ERA} is {@link GregorianCalendar#BC} + */ + public JewishDate(ZonedDateTime zonedDateTime) { + setGregorianDate(zonedDateTime); + } + + /** + * A constructor that initializes the date to the {@link java.time.LocalDate LocalDate} parameter. + * + * @param localDate + * the LocalDate to set the calendar to + * @throws IllegalArgumentException + * if the {@link Calendar#ERA} is {@link GregorianCalendar#BC} + */ + public JewishDate(LocalDate localDate) { + setGregorianDate(localDate); + } + + /** + * Sets the date based on a {@link java.util.Calendar Calendar} object. Modifies the Jewish date as well. + * + * @param zonedDateTime + * the ZonedDateTime to set the calendar to + * @throws IllegalArgumentException + * if the {@link Calendar#ERA} is {@link GregorianCalendar#BC} + */ + public void setGregorianDate(ZonedDateTime zonedDateTime) { + setGregorianDate(zonedDateTime.toLocalDate()); + } + + /** + * Sets the date based on a {@link java.time.LocalDate LocalDate} object. Modifies the Jewish date as well. + * + * @param localDate + * the LocalDate to set the calendar to + * @throws IllegalArgumentException + * if the date would fall prior to the year 1 AD + */ + public void setGregorianDate(LocalDate localDate) { + int absDate = gregorianDateToAbsDate(localDate.getYear(), localDate.getMonth().getValue(), localDate.getDayOfMonth()); + + // convert to Jewish date + setAbsDate(absDate); + } + + /** + * Sets the Jewish Date and updates the Gregorian date accordingly. + * + * @param year + * the Jewish year. The year can't be negative + * @param month + * the Jewish month starting with Nissan. A value of 1 is expected for Nissan ... 12 for Adar and 13 for + * Adar II. Use the constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar + * II) to avoid any confusion. + * @param dayOfMonth + * the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only + * has 29 days, the day will be set as 29. + * @throws IllegalArgumentException + * if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month < 1 or > 12 (or 13 on a + * leap year) or the day of month is < 1 or > 30 is passed in + */ + public void setJewishDate(int year, int month, int dayOfMonth) { + setJewishDate(year, month, dayOfMonth, getMoladHours(), getMoladMinutes(), getMoladChalakim()); + } + + /** + * Sets the Jewish Date and updates the Gregorian date accordingly. + * + * @param year + * the Jewish year. The year can't be negative + * @param month + * the Jewish month starting with Nissan. A value of 1 is expected for Nissan ... 12 for Adar and 13 for + * Adar II. Use the constants {@link #NISSAN} ... {@link #ADAR} (or {@link #ADAR_II} for a leap year Adar + * II) to avoid any confusion. + * @param dayOfMonth + * the Jewish day of month. valid values are 1-30. If the day of month is set to 30 for a month that only + * has 29 days, the day will be set as 29. + * + * @param hours + * the hour of the day. Used for molad calculations + * @param minutes + * the minutes. Used for molad calculations + * @param chalakim + * the chalakim / parts. Used for molad calculations. The chalakim should not + * exceed 17. Minutes should be used for larger numbers. + * + * @throws IllegalArgumentException + * if a Jewish date earlier than 18 Teves, 3761 (1/1/1 Gregorian), a month < 1 or > 12 (or 13 on a leap year), the day + * of month is < 1 or > 30, an hour < 0 or > 23, a minute < 0 > 59 or chalakim < 0 > 17. For + * larger a larger number of chalakim 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). + */ + public void setJewishDate(int year, int month, int dayOfMonth, int hours, int minutes, int chalakim) { + + validateJewishDate(year, month, dayOfMonth, hours, minutes, chalakim); + + jewishMonth = month; + jewishDay = dayOfMonth; + jewishYear = year; + moladHours = hours; + moladMinutes = minutes; + moladChalakim = chalakim; + + gregorianAbsDate = jewishDateToAbsDate(jewishYear, jewishMonth, jewishDay); // reset Gregorian date + + dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1; // reset day of week + } + + public void setJewishDayOfMonth(int dayOfMonth){ + setJewishDate(getJewishYear(), getJewishMonth(), dayOfMonth); + } + + public void setJewishMonth(int month){ + int year = getJewishYear(); + int day = Math.min(getDaysInJewishMonth(month,year),getJewishDayOfMonth()); + setJewishDate(year, month, day); + } + + public void setJewishYear(int year){ + int month = Math.min(getJewishMonth(),getLastMonthOfJewishYear(year)); + int day = Math.min(getJewishDayOfMonth(), getDaysInJewishMonth(month,year)); + setJewishDate(year, month, day); + } + + + /** + * Returns this object's date as a {@link java.time.LocalDate} object. + * + * @return The {@link java.time.LocalDate} + */ + public LocalDate getLocalDate() { + return absDateToDate(getAbsDate()); + } + + /** + * Resets this date to the current system date. + */ + public void resetDate() { + LocalDate localDate = LocalDate.now(); + setGregorianDate(localDate); + } + + public void minusDays(int days){ + if (days < 1) { + throw new IllegalArgumentException("the amount of days to subtract has to be greater than zero."); + } + setAbsDate(getAbsDate() - days); + + } + public void addDays(int days){ + if (days < 1) { + throw new IllegalArgumentException("the amount of days to add has to be greater than zero."); + } + setAbsDate(getAbsDate() + days); + } + public void addMonths(int months){ + if (months < 1) { + throw new IllegalArgumentException("the amount of months to add has to be greater than zero."); + } + int year = getJewishYear(); + int month = getJewishMonth(); + for (int i = 0; i < months; i++) { + if (month == ELUL) { + month = TISHREI; + year++; + } else if ((! isJewishLeapYear(year) && month == ADAR) + || (isJewishLeapYear(year) && month == ADAR_II)){ + month = NISSAN; + } else { + month++; + } + } + int day = Math.min(getJewishDayOfMonth(), getDaysInJewishMonth(month,year)); + setJewishDate(year, month, day); + } + public void addYears(int years, boolean useAdarAlephForLeapYear){ + if (years < 1) { + throw new IllegalArgumentException("the amount of years to add has to be greater than zero."); + } + int targetYear = getJewishYear() + years; + // If we are in the month of Adar in a non-leap year and we are skipping + // to a year that is a leap year, we will use useAdarAlephInYear do + // decide which month to skip to. + int month; + if (getJewishMonth() == JewishDate.ADAR && !isJewishLeapYear(getJewishYear()) && isJewishLeapYear(targetYear)){ + if (useAdarAlephForLeapYear){ + month = JewishDate.ADAR; + }else{ + month = JewishDate.ADAR_II; + } + } else{ + // If we are in JewishDate.ADAR_II, this will clamp the month to 12 (JewishDate.ADAR) + month = Math.min(getJewishMonth(),getLastMonthOfJewishYear(targetYear)); + } + // Clamp to final day of the month + int day = Math.min(getJewishDayOfMonth(), getDaysInJewishMonth(month,targetYear)); + setJewishDate(targetYear, month, day); + } + + + + /** + * Returns a string containing the Jewish date in the form, "day Month, year" e.g. "21 Shevat, 5729". For more + * complex formatting, use the formatter classes. + * + * @return the Jewish date in the form "day Month, year" e.g. "21 Shevat, 5729" + * @see HebrewDateFormatter#format(JewishDate) + */ + public String toString() { + return new HebrewDateFormatter().format(this); + } + + /** + * Indicates whether some other object is "equal to" this one. + * @see Object#equals(Object) + */ + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + JewishDate jewishDate = (JewishDate) object; + return gregorianAbsDate == jewishDate.getAbsDate(); + } + + /** + * Compares two dates as per the compareTo() method in the Comparable interface. Returns a value less than 0 if this + * date is "less than" (before) the date, greater than 0 if this date is "greater than" (after) the date, or 0 if + * they are equal. + */ + public int compareTo(JewishDate jewishDate) { + return Integer.compare(gregorianAbsDate, jewishDate.getAbsDate()); + } + + /** + * Returns the Jewish month 1-12 (or 13 years in a leap year). The month count starts with 1 for Nissan and goes to + * 13 for Adar II + * + * @return the Jewish month from 1 to 12 (or 13 years in a leap year). The month count starts with 1 for Nissan and + * goes to 13 for Adar II + */ + public int getJewishMonth() { + return jewishMonth; + } + + /** + * Returns the Jewish day of month. + * + * @return the Jewish day of the month + */ + public int getJewishDayOfMonth() { + return jewishDay; + } + + /** + * Returns the Jewish year. + * + * @return the Jewish year + */ + public int getJewishYear() { + return jewishYear; + } + + /** + * Returns the day of the week as a number between 1-7. + * + * @return the day of the week as a number between 1-7. + */ + public int getDayOfWeek() { + return dayOfWeek; + } + + /** + * A method that creates a deep copy of the object. + * + * @see Object#clone() + */ + public Object clone() { + JewishDate clone = null; + try { + clone = (JewishDate) super.clone(); + } catch (CloneNotSupportedException cnse) { + // Required by the compiler. Should never be reached since we implement clone() + } + if (clone != null) { + clone.setAbsDate(getAbsDate()); + clone.setMoladHours(getMoladHours()); + clone.setMoladMinutes(getMoladMinutes()); + clone.setMoladChalakim(getMoladChalakim()); + } + return clone; + } + + /** + * Overrides {@link Object#hashCode()}. + * @see Object#hashCode() + */ + public int hashCode() { + return Integer.hashCode(gregorianAbsDate); + } } diff --git a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/TefilaRules.java b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/TefilaRules.java index 7e1c3b2b..0683bb95 100644 --- a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/TefilaRules.java +++ b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/TefilaRules.java @@ -215,7 +215,7 @@ public boolean isTachanunRecitedShacharis(JewishCalendar jewishCalendar) { */ public boolean isTachanunRecitedMincha(JewishCalendar jewishCalendar) { JewishCalendar tomorrow = (JewishCalendar) jewishCalendar.clone(); - tomorrow.forward(Calendar.DATE, 1); + tomorrow.addDays(1); if (! tachanunRecitedMinchaAllYear || jewishCalendar.getDayOfWeek() == Calendar.FRIDAY diff --git a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/YerushalmiYomiCalculator.java b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/YerushalmiYomiCalculator.java index a1927404..e444b26f 100644 --- a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/YerushalmiYomiCalculator.java +++ b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/YerushalmiYomiCalculator.java @@ -15,8 +15,8 @@ */ package com.kosherjava.zmanim.hebrewcalendar; -import java.time.ZoneId; -import java.time.ZonedDateTime; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; /** * This class calculates the Talmud Yerusalmi blatt/dafim) in Shas*/ private static final int WHOLE_SHAS_DAFS = 1554; @@ -56,8 +53,7 @@ public YerushalmiYomiCalculator() { * @return the daf. */ public static Daf getDafYomiYerushalmi(JewishCalendar jewishCalendar) { - ZonedDateTime requested = jewishCalendar.getGregorianCalendar().toInstant() - .atZone(ZoneId.systemDefault()); + LocalDate requested = jewishCalendar.getLocalDate(); int masechta = 0; Daf dafYomi = null; @@ -73,8 +69,8 @@ public static Daf getDafYomiYerushalmi(JewishCalendar jewishCalendar) { } // Initialize cycle dates - ZonedDateTime nextCycle = DAF_YOMI_START_DAY; - ZonedDateTime prevCycle = DAF_YOMI_START_DAY; + LocalDate nextCycle = DAF_YOMI_START_DAY; + LocalDate prevCycle = DAF_YOMI_START_DAY; // Loop through cycles until we reach the requested date while (requested.isAfter(nextCycle)) { @@ -107,10 +103,10 @@ public static Daf getDafYomiYerushalmi(JewishCalendar jewishCalendar) { /** * Counts the number of "special days" (Yom Kippur, Tisha B’Av) between two ZonedDateTimes. * @param start the start date for the calculation - * @param end the start date for the calculatio + * @param end the start date for the calculation * @return the number of special days */ - private static int getNumOfSpecialDays(ZonedDateTime start, ZonedDateTime end) { + private static int getNumOfSpecialDays(LocalDate start, LocalDate end) { int startYear = new JewishCalendar(start).getJewishYear(); int endYear = new JewishCalendar(end).getJewishYear(); @@ -126,10 +122,8 @@ private static int getNumOfSpecialDays(ZonedDateTime start, ZonedDateTime end) { yomKippur.setJewishYear(year); tishaBeav.setJewishYear(year); - ZonedDateTime ykDate = yomKippur.getGregorianCalendar().toInstant() - .atZone(start.getZone()); - ZonedDateTime tbDate = tishaBeav.getGregorianCalendar().toInstant() - .atZone(start.getZone()); + LocalDate ykDate = yomKippur.getLocalDate(); + LocalDate tbDate = tishaBeav.getLocalDate(); if (isBetween(start, ykDate, end)) specialDays++; if (isBetween(start, tbDate, end)) specialDays++; @@ -145,7 +139,7 @@ private static int getNumOfSpecialDays(ZonedDateTime start, ZonedDateTime end) { * @param end the end ZonedDateTime * @return if the date is between the two dates */ - private static boolean isBetween(ZonedDateTime start, ZonedDateTime date, ZonedDateTime end) { + private static boolean isBetween(LocalDate start, LocalDate date, LocalDate end) { return start.isBefore(date) && end.isAfter(date); } @@ -155,7 +149,7 @@ private static boolean isBetween(ZonedDateTime start, ZonedDateTime date, ZonedD * @param end the end ZonedDateTime * @return the number of days between the dates. */ - private static long getDiffBetweenDays(ZonedDateTime start, ZonedDateTime end) { - return (end.toInstant().toEpochMilli() - start.toInstant().toEpochMilli()) / DAY_MILLIS; + private static long getDiffBetweenDays(LocalDate start, LocalDate end) { + return ChronoUnit.DAYS.between(start, end); } } diff --git a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/YomiCalculator.java b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/YomiCalculator.java index 90ba0b8c..cbf7e877 100644 --- a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/YomiCalculator.java +++ b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/YomiCalculator.java @@ -15,6 +15,8 @@ */ package com.kosherjava.zmanim.hebrewcalendar; +import java.time.LocalDate; +import java.time.Month; import java.util.Calendar; import java.util.GregorianCalendar; @@ -30,14 +32,14 @@ public class YomiCalculator { /** * The start date of the first Daf Yomi Bavli cycle of September 11, 1923 / Rosh Hashana 5684. */ - private static final Calendar dafYomiStartDay = new GregorianCalendar(1923, Calendar.SEPTEMBER, 11); + private static final LocalDate dafYomiStartDay = LocalDate.of(1923, Month.SEPTEMBER,11); /** The start date of the first Daf Yomi Bavli cycle in the Julian calendar. Used internally for calculations.*/ private static final int dafYomiJulianStartDay = getJulianDay(dafYomiStartDay); /** * The date that the pagination for the Daf Yomi Maseches Shekalim changed to use the commonly used Vilna * Shas pagination from the no longer commonly available Zhitomir / Slavuta Shas used by Rabbi Meir Shapiro. */ - private static final Calendar shekalimChangeDay = new GregorianCalendar(1975, Calendar.JUNE, 24); + private static final LocalDate shekalimChangeDay = LocalDate.of(1975, Month.JUNE, 24); /** The Julian date that the cycle for Shekalim changed. * @see #getDafYomiBavli(JewishCalendar) for details. @@ -83,18 +85,18 @@ public static Daf getDafYomiBavli(JewishCalendar jewishCalendar) { */ int[] blattPerMasechta = { 64, 157, 105, 121, 22, 88, 56, 40, 35, 31, 32, 29, 27, 122, 112, 91, 66, 49, 90, 82, 119, 119, 176, 113, 24, 49, 76, 14, 120, 110, 142, 61, 34, 34, 28, 22, 4, 9, 5, 73 }; - Calendar calendar = jewishCalendar.getGregorianCalendar(); + LocalDate date = jewishCalendar.getLocalDate(); Daf dafYomi = null; - int julianDay = getJulianDay(calendar); + int julianDay = getJulianDay(date); int cycleNo; int dafNo; - if (calendar.before(dafYomiStartDay)) { + if (date.isBefore(dafYomiStartDay) ) { // TODO: should we return a null or throw an IllegalArgumentException? - throw new IllegalArgumentException(calendar + " is prior to organized Daf Yomi Bavli cycles that started on " + throw new IllegalArgumentException(date + " is prior to organized Daf Yomi Bavli cycles that started on " + dafYomiStartDay); } - if (calendar.equals(shekalimChangeDay) || calendar.after(shekalimChangeDay)) { + if (date.equals(shekalimChangeDay) || date.isAfter(shekalimChangeDay)) { cycleNo = 8 + ((julianDay - shekalimJulianChangeDay) / 2711); dafNo = ((julianDay - shekalimJulianChangeDay) % 2711); } else { @@ -140,10 +142,10 @@ public static Daf getDafYomiBavli(JewishCalendar jewishCalendar) { * The Java Calendar of the date to be calculated * @return the Julian day number corresponding to the date */ - private static int getJulianDay(Calendar calendar) { - int year = calendar.get(Calendar.YEAR); - int month = calendar.get(Calendar.MONTH) + 1; - int day = calendar.get(Calendar.DAY_OF_MONTH); + private static int getJulianDay(LocalDate localDate) { + int year = localDate.getYear(); + int month = localDate.getMonthValue() ; + int day = localDate.getDayOfMonth(); if (month <= 2) { year -= 1; month += 12; diff --git a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/RegressionTestFileWriter.java b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/RegressionTestFileWriter.java index 485df83b..afafa4b5 100644 --- a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/RegressionTestFileWriter.java +++ b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/RegressionTestFileWriter.java @@ -4,7 +4,9 @@ import com.kosherjava.zmanim.util.GeoLocation; import java.io.*; +import java.time.Instant; import java.time.LocalDate; +import java.time.ZoneId; import java.util.*; public class RegressionTestFileWriter { @@ -14,9 +16,9 @@ public static void main(String[] args) throws IOException { LocalDate end = LocalDate.of(9999, 1, 1); LocalDate current = start; JewishCalendar cal = new JewishCalendar(current); - GregorianCalendar gregorian = new GregorianCalendar(current.getYear(), current.getMonthValue() - 1, current.getDayOfMonth()); + LocalDate gregorian = LocalDate.of(current.getYear(), current.getMonthValue() , current.getDayOfMonth()); JewishDate date = new JewishDate(current); - ComprehensiveZmanimCalendar zcal = new ComprehensiveZmanimCalendar(new GeoLocation("Lakewood, NJ", 40.096, -74.222, 29.02, TimeZone.getTimeZone("America/New_York"))); + ComprehensiveZmanimCalendar zcal = new ComprehensiveZmanimCalendar(new GeoLocation("Lakewood, NJ", 40.096, -74.222, 29.02, ZoneId.of("America/New_York"))); List calendars = new ArrayList<>(); List zmanim = new ArrayList<>(); @@ -35,7 +37,7 @@ public static void main(String[] args) throws IOException { cal.isErevYomTov(), cal.isErevRoshChodesh(), cal.isYomKippurKatan(), cal.isBeHaB(), cal.isTaanis(), cal.isTaanisBechoros(), cal.getDayOfChanukah(), cal.isChanukah(), cal.isPurim(), cal.isRoshChodesh(), cal.isMacharChodesh(), cal.isShabbosMevorchim(), cal.getDayOfOmer(), - cal.isTishaBav(), cal.getMolad(), cal.getMoladAsDate(), cal.getTchilasZmanKidushLevana3Days(), + cal.isTishaBav(), cal.getMolad(), cal.getMoladAsInstant(), cal.getTchilasZmanKidushLevana3Days(), cal.getTchilasZmanKidushLevana7Days(), cal.getSofZmanKidushLevanaBetweenMoldos(), cal.getSofZmanKidushLevana15Days(), cal.getTekufasTishreiElapsedDays())); @@ -126,10 +128,10 @@ public static void main(String[] args) throws IOException { cal.isMoridHatalRecited();*/ current = current.plusDays(1L); - gregorian.roll(Calendar.DATE, true); - date.forward(Calendar.DATE, 1); - cal.setDate(current); - zcal.setCalendar(gregorian); + gregorian = gregorian.plusDays(1); + date.addDays(1); + cal.setGregorianDate(current); + zcal.setLocalDate(gregorian); } //write calendars to file: @@ -324,71 +326,71 @@ public String toString() { } public FullZmanim(long getShaahZmanis19Point8Degrees, long getShaahZmanis18Degrees, - long getShaahZmanis26Degrees, long getShaahZmanis16Point1Degrees, long getShaahZmanis60Minutes, - long getShaahZmanis72Minutes, long getShaahZmanis72MinutesZmanis, long getShaahZmanis90Minutes, - long getShaahZmanis90MinutesZmanis, long getShaahZmanis96MinutesZmanis, long getShaahZmanisAteretTorah, - long getShaahZmanisAlos16Point1ToTzais3Point8, long getShaahZmanisAlos16Point1ToTzais3Point7, - long getShaahZmanis96Minutes, long getShaahZmanis120Minutes, long getShaahZmanis120MinutesZmanis, - Date getPlagHamincha120MinutesZmanis, Date getPlagHamincha120Minutes, Date getAlos60, - Date getAlos72Zmanis, Date getAlos96, Date getAlos90Zmanis, Date getAlos96Zmanis, Date getAlos90, - Date getAlos120, Date getAlos120Zmanis, Date getAlos26Degrees, Date getAlos18Degrees, - Date getAlos19Degrees, Date getAlos19Point8Degrees, Date getAlos16Point1Degrees, - Date getMisheyakir11Point5Degrees, Date getMisheyakir11Degrees, Date getMisheyakir10Point2Degrees, - Date getMisheyakir7Point65Degrees, Date getMisheyakir9Point5Degrees, - Date getSofZmanShmaMGA19Point8Degrees, Date getSofZmanShmaMGA16Point1Degrees, - Date getSofZmanShmaMGA18Degrees, Date getSofZmanShmaMGA72Minutes, Date getSofZmanShmaMGA72MinutesZmanis, - Date getSofZmanShmaMGA90Minutes, Date getSofZmanShmaMGA90MinutesZmanis, Date getSofZmanShmaMGA96Minutes, - Date getSofZmanShmaMGA96MinutesZmanis, Date getSofZmanShma3HoursBeforeChatzos, - Date getSofZmanShmaMGA120Minutes, Date getSofZmanShmaAlos16Point1ToSunset, - Date getSofZmanShmaAlos16Point1ToTzaisGeonim7Point083Degrees, - Date getSofZmanTfilaMGA19Point8Degrees, Date getSofZmanTfilaMGA16Point1Degrees, - Date getSofZmanTfilaMGA18Degrees, Date getSofZmanTfilaMGA72Minutes, - Date getSofZmanTfilaMGA72MinutesZmanis, Date getSofZmanTfilaMGA90Minutes, - Date getSofZmanTfilaMGA90MinutesZmanis, Date getSofZmanTfilaMGA96Minutes, - Date getSofZmanTfilaMGA96MinutesZmanis, Date getSofZmanTfilaMGA120Minutes, - Date getSofZmanTfila2HoursBeforeChatzos, Date getMinchaGedola30Minutes, Date getMinchaGedola72Minutes, - Date getMinchaGedola16Point1Degrees, Date getMinchaGedolaAhavatShalom, - Date getMinchaGedolaGreaterThan30, Date getMinchaKetana16Point1Degrees, - Date getMinchaKetanaAhavatShalom, Date getMinchaKetana72Minutes, Date getPlagHamincha60Minutes, - Date getPlagHamincha72Minutes, Date getPlagHamincha90Minutes, Date getPlagHamincha96Minutes, - Date getPlagHamincha96MinutesZmanis, Date getPlagHamincha90MinutesZmanis, - Date getPlagHamincha72MinutesZmanis, Date getPlagHamincha16Point1Degrees, - Date getPlagHamincha19Point8Degrees, Date getPlagHamincha26Degrees, Date getPlagHamincha18Degrees, - Date getPlagAlosToSunset, Date getPlagAlos16Point1ToTzaisGeonim7Point083Degrees, - Date getPlagAhavatShalom, Date getBainHashmashosRT13Point24Degrees, - Date getBainHashmashosRT58Point5Minutes, Date getBainHashmashosRT13Point5MinutesBefore7Point083Degrees, - Date getBainHashmashosRT2Stars, Date getBainHashmashosYereim18Minutes, - Date getBainHashmashosYereim3Point05Degrees, Date getBainHashmashosYereim16Point875Minutes, - Date getBainHashmashosYereim2Point8Degrees, Date getBainHashmashosYereim13Point5Minutes, - Date getBainHashmashosYereim2Point1Degrees, Date getTzaisGeonim3Point7Degrees, - Date getTzaisGeonim3Point8Degrees, Date getTzaisGeonim5Point95Degrees, - Date getTzaisGeonim4Point61Degrees, Date getTzaisGeonim4Point37Degrees, - Date getTzaisGeonim5Point88Degrees, Date getTzaisGeonim4Point8Degrees, - Date getTzaisGeonim6Point45Degrees, Date getTzaisGeonim7Point083Degrees, - Date getTzaisGeonim7Point67Degrees, Date getTzaisGeonim8Point5Degrees, - Date getTzaisGeonim9Point3Degrees, Date getTzaisGeonim9Point75Degrees, Date getTzais60, - Date getTzaisAteretTorah, Date getSofZmanShmaAteretTorah, Date getSofZmanTfilahAteretTorah, - Date getMinchaGedolaAteretTorah, Date getMinchaKetanaAteretTorah, Date getPlagHaminchaAteretTorah, - Date getTzais72Zmanis, Date getTzais90Zmanis, Date getTzais96Zmanis, Date getTzais90, Date getTzais120, - Date getTzais120Zmanis, Date getTzais16Point1Degrees, Date getTzais26Degrees, Date getTzais18Degrees, - Date getTzais19Point8Degrees, Date getTzais96, Date getFixedLocalChatzos, - Date getSofZmanKidushLevanaBetweenMoldos, - Date getSofZmanKidushLevana15Days, Date getTchilasZmanKidushLevana3Days, Date getZmanMolad, - Date getTchilasZmanKidushLevana7Days, Date getSofZmanAchilasChametzGRA, - Date getSofZmanAchilasChametzMGA72Minutes, Date getSofZmanAchilasChametzMGA16Point1Degrees, - Date getSofZmanBiurChametzGRA, Date getSofZmanBiurChametzMGA72Minutes, - Date getSofZmanBiurChametzMGA16Point1Degrees, Date getSolarMidnight, long getShaahZmanisBaalHatanya, - Date getAlosBaalHatanya, Date getSofZmanShmaBaalHatanya, Date getSofZmanTfilaBaalHatanya, - Date getSofZmanAchilasChametzBaalHatanya, Date getSofZmanBiurChametzBaalHatanya, - Date getMinchaGedolaBaalHatanya, Date getMinchaGedolaBaalHatanyaGreaterThan30, - Date getMinchaKetanaBaalHatanya, Date getPlagHaminchaBaalHatanya, Date getTzaisBaalHatanya, - Date getSofZmanShmaMGA18DegreesToFixedLocalChatzos, - Date getSofZmanShmaMGA16Point1DegreesToFixedLocalChatzos, - Date getSofZmanShmaMGA90MinutesToFixedLocalChatzos, Date getSofZmanShmaMGA72MinutesToFixedLocalChatzos, - Date getSofZmanShmaGRASunriseToFixedLocalChatzos, Date getSofZmanTfilaGRASunriseToFixedLocalChatzos, - Date getMinchaGedolaGRAFixedLocalChatzos30Minutes, Date getMinchaKetanaGRAFixedLocalChatzosToSunset, - Date getPlagHaminchaGRAFixedLocalChatzosToSunset, Date getTzais50, Date getSamuchLeMinchaKetanaGRA, - Date getSamuchLeMinchaKetana16Point1Degrees, Date getSamuchLeMinchaKetana72Minutes) { + long getShaahZmanis26Degrees, long getShaahZmanis16Point1Degrees, long getShaahZmanis60Minutes, + long getShaahZmanis72Minutes, long getShaahZmanis72MinutesZmanis, long getShaahZmanis90Minutes, + long getShaahZmanis90MinutesZmanis, long getShaahZmanis96MinutesZmanis, long getShaahZmanisAteretTorah, + long getShaahZmanisAlos16Point1ToTzais3Point8, long getShaahZmanisAlos16Point1ToTzais3Point7, + long getShaahZmanis96Minutes, long getShaahZmanis120Minutes, long getShaahZmanis120MinutesZmanis, + Instant getPlagHamincha120MinutesZmanis, Instant getPlagHamincha120Minutes, Instant getAlos60, + Instant getAlos72Zmanis, Instant getAlos96, Instant getAlos90Zmanis, Instant getAlos96Zmanis, Instant getAlos90, + Instant getAlos120, Instant getAlos120Zmanis, Instant getAlos26Degrees, Instant getAlos18Degrees, + Instant getAlos19Degrees, Instant getAlos19Point8Degrees, Instant getAlos16Point1Degrees, + Instant getMisheyakir11Point5Degrees, Instant getMisheyakir11Degrees, Instant getMisheyakir10Point2Degrees, + Instant getMisheyakir7Point65Degrees, Instant getMisheyakir9Point5Degrees, + Instant getSofZmanShmaMGA19Point8Degrees, Instant getSofZmanShmaMGA16Point1Degrees, + Instant getSofZmanShmaMGA18Degrees, Instant getSofZmanShmaMGA72Minutes, Instant getSofZmanShmaMGA72MinutesZmanis, + Instant getSofZmanShmaMGA90Minutes, Instant getSofZmanShmaMGA90MinutesZmanis, Instant getSofZmanShmaMGA96Minutes, + Instant getSofZmanShmaMGA96MinutesZmanis, Instant getSofZmanShma3HoursBeforeChatzos, + Instant getSofZmanShmaMGA120Minutes, Instant getSofZmanShmaAlos16Point1ToSunset, + Instant getSofZmanShmaAlos16Point1ToTzaisGeonim7Point083Degrees, + Instant getSofZmanTfilaMGA19Point8Degrees, Instant getSofZmanTfilaMGA16Point1Degrees, + Instant getSofZmanTfilaMGA18Degrees, Instant getSofZmanTfilaMGA72Minutes, + Instant getSofZmanTfilaMGA72MinutesZmanis, Instant getSofZmanTfilaMGA90Minutes, + Instant getSofZmanTfilaMGA90MinutesZmanis, Instant getSofZmanTfilaMGA96Minutes, + Instant getSofZmanTfilaMGA96MinutesZmanis, Instant getSofZmanTfilaMGA120Minutes, + Instant getSofZmanTfila2HoursBeforeChatzos, Instant getMinchaGedola30Minutes, Instant getMinchaGedola72Minutes, + Instant getMinchaGedola16Point1Degrees, Instant getMinchaGedolaAhavatShalom, + Instant getMinchaGedolaGreaterThan30, Instant getMinchaKetana16Point1Degrees, + Instant getMinchaKetanaAhavatShalom, Instant getMinchaKetana72Minutes, Instant getPlagHamincha60Minutes, + Instant getPlagHamincha72Minutes, Instant getPlagHamincha90Minutes, Instant getPlagHamincha96Minutes, + Instant getPlagHamincha96MinutesZmanis, Instant getPlagHamincha90MinutesZmanis, + Instant getPlagHamincha72MinutesZmanis, Instant getPlagHamincha16Point1Degrees, + Instant getPlagHamincha19Point8Degrees, Instant getPlagHamincha26Degrees, Instant getPlagHamincha18Degrees, + Instant getPlagAlosToSunset, Instant getPlagAlos16Point1ToTzaisGeonim7Point083Degrees, + Instant getPlagAhavatShalom, Instant getBainHashmashosRT13Point24Degrees, + Instant getBainHashmashosRT58Point5Minutes, Instant getBainHashmashosRT13Point5MinutesBefore7Point083Degrees, + Instant getBainHashmashosRT2Stars, Instant getBainHashmashosYereim18Minutes, + Instant getBainHashmashosYereim3Point05Degrees, Instant getBainHashmashosYereim16Point875Minutes, + Instant getBainHashmashosYereim2Point8Degrees, Instant getBainHashmashosYereim13Point5Minutes, + Instant getBainHashmashosYereim2Point1Degrees, Instant getTzaisGeonim3Point7Degrees, + Instant getTzaisGeonim3Point8Degrees, Instant getTzaisGeonim5Point95Degrees, + Instant getTzaisGeonim4Point61Degrees, Instant getTzaisGeonim4Point37Degrees, + Instant getTzaisGeonim5Point88Degrees, Instant getTzaisGeonim4Point8Degrees, + Instant getTzaisGeonim6Point45Degrees, Instant getTzaisGeonim7Point083Degrees, + Instant getTzaisGeonim7Point67Degrees, Instant getTzaisGeonim8Point5Degrees, + Instant getTzaisGeonim9Point3Degrees, Instant getTzaisGeonim9Point75Degrees, Instant getTzais60, + Instant getTzaisAteretTorah, Instant getSofZmanShmaAteretTorah, Instant getSofZmanTfilahAteretTorah, + Instant getMinchaGedolaAteretTorah, Instant getMinchaKetanaAteretTorah, Instant getPlagHaminchaAteretTorah, + Instant getTzais72Zmanis, Instant getTzais90Zmanis, Instant getTzais96Zmanis, Instant getTzais90, Instant getTzais120, + Instant getTzais120Zmanis, Instant getTzais16Point1Degrees, Instant getTzais26Degrees, Instant getTzais18Degrees, + Instant getTzais19Point8Degrees, Instant getTzais96, Instant getFixedLocalChatzos, + Instant getSofZmanKidushLevanaBetweenMoldos, + Instant getSofZmanKidushLevana15Days, Instant getTchilasZmanKidushLevana3Days, Instant getZmanMolad, + Instant getTchilasZmanKidushLevana7Days, Instant getSofZmanAchilasChametzGRA, + Instant getSofZmanAchilasChametzMGA72Minutes, Instant getSofZmanAchilasChametzMGA16Point1Degrees, + Instant getSofZmanBiurChametzGRA, Instant getSofZmanBiurChametzMGA72Minutes, + Instant getSofZmanBiurChametzMGA16Point1Degrees, Instant getSolarMidnight, long getShaahZmanisBaalHatanya, + Instant getAlosBaalHatanya, Instant getSofZmanShmaBaalHatanya, Instant getSofZmanTfilaBaalHatanya, + Instant getSofZmanAchilasChametzBaalHatanya, Instant getSofZmanBiurChametzBaalHatanya, + Instant getMinchaGedolaBaalHatanya, Instant getMinchaGedolaBaalHatanyaGreaterThan30, + Instant getMinchaKetanaBaalHatanya, Instant getPlagHaminchaBaalHatanya, Instant getTzaisBaalHatanya, + Instant getSofZmanShmaMGA18DegreesToFixedLocalChatzos, + Instant getSofZmanShmaMGA16Point1DegreesToFixedLocalChatzos, + Instant getSofZmanShmaMGA90MinutesToFixedLocalChatzos, Instant getSofZmanShmaMGA72MinutesToFixedLocalChatzos, + Instant getSofZmanShmaGRASunriseToFixedLocalChatzos, Instant getSofZmanTfilaGRASunriseToFixedLocalChatzos, + Instant getMinchaGedolaGRAFixedLocalChatzos30Minutes, Instant getMinchaKetanaGRAFixedLocalChatzosToSunset, + Instant getPlagHaminchaGRAFixedLocalChatzosToSunset, Instant getTzais50, Instant getSamuchLeMinchaKetanaGRA, + Instant getSamuchLeMinchaKetana16Point1Degrees, Instant getSamuchLeMinchaKetana72Minutes) { this.getShaahZmanis19Point8Degrees = getShaahZmanis19Point8Degrees; this.getShaahZmanis18Degrees = getShaahZmanis18Degrees; this.getShaahZmanis26Degrees = getShaahZmanis26Degrees; @@ -567,176 +569,176 @@ public FullZmanim(long getShaahZmanis19Point8Degrees, long getShaahZmanis18Degre public final long getShaahZmanis96Minutes; public final long getShaahZmanis120Minutes; public final long getShaahZmanis120MinutesZmanis; - public final Date getPlagHamincha120MinutesZmanis; - public final Date getPlagHamincha120Minutes; - public final Date getAlos60; - public final Date getAlos72Zmanis; - public final Date getAlos96; - public final Date getAlos90Zmanis; - public final Date getAlos96Zmanis; - public final Date getAlos90; - public final Date getAlos120; - public final Date getAlos120Zmanis; - public final Date getAlos26Degrees; - public final Date getAlos18Degrees; - public final Date getAlos19Degrees; - public final Date getAlos19Point8Degrees; - public final Date getAlos16Point1Degrees; - public final Date getMisheyakir11Point5Degrees; - public final Date getMisheyakir11Degrees; - public final Date getMisheyakir10Point2Degrees; - public final Date getMisheyakir7Point65Degrees; - public final Date getMisheyakir9Point5Degrees; - public final Date getSofZmanShmaMGA19Point8Degrees; - public final Date getSofZmanShmaMGA16Point1Degrees; - public final Date getSofZmanShmaMGA18Degrees; - public final Date getSofZmanShmaMGA72Minutes; - public final Date getSofZmanShmaMGA72MinutesZmanis; - public final Date getSofZmanShmaMGA90Minutes; - public final Date getSofZmanShmaMGA90MinutesZmanis; - public final Date getSofZmanShmaMGA96Minutes; - public final Date getSofZmanShmaMGA96MinutesZmanis; - public final Date getSofZmanShma3HoursBeforeChatzos; - public final Date getSofZmanShmaMGA120Minutes; - public final Date getSofZmanShmaAlos16Point1ToSunset; - public final Date getSofZmanShmaAlos16Point1ToTzaisGeonim7Point083Degrees; - public final Date getSofZmanTfilaMGA19Point8Degrees; - public final Date getSofZmanTfilaMGA16Point1Degrees; - public final Date getSofZmanTfilaMGA18Degrees; - public final Date getSofZmanTfilaMGA72Minutes; - public final Date getSofZmanTfilaMGA72MinutesZmanis; - public final Date getSofZmanTfilaMGA90Minutes; - public final Date getSofZmanTfilaMGA90MinutesZmanis; - public final Date getSofZmanTfilaMGA96Minutes; - public final Date getSofZmanTfilaMGA96MinutesZmanis; - public final Date getSofZmanTfilaMGA120Minutes; - public final Date getSofZmanTfila2HoursBeforeChatzos; - public final Date getMinchaGedola30Minutes; - public final Date getMinchaGedola72Minutes; - public final Date getMinchaGedola16Point1Degrees; - public final Date getMinchaGedolaAhavatShalom; - public final Date getMinchaGedolaGreaterThan30; - public final Date getMinchaKetana16Point1Degrees; - public final Date getMinchaKetanaAhavatShalom; - public final Date getMinchaKetana72Minutes; - public final Date getPlagHamincha60Minutes; - public final Date getPlagHamincha72Minutes; - public final Date getPlagHamincha90Minutes; - public final Date getPlagHamincha96Minutes; - public final Date getPlagHamincha96MinutesZmanis; - public final Date getPlagHamincha90MinutesZmanis; - public final Date getPlagHamincha72MinutesZmanis; - public final Date getPlagHamincha16Point1Degrees; - public final Date getPlagHamincha19Point8Degrees; - public final Date getPlagHamincha26Degrees; - public final Date getPlagHamincha18Degrees; - public final Date getPlagAlosToSunset; - public final Date getPlagAlos16Point1ToTzaisGeonim7Point083Degrees; - public final Date getPlagAhavatShalom; - public final Date getBainHashmashosRT13Point24Degrees; - public final Date getBainHashmashosRT58Point5Minutes; - public final Date getBainHashmashosRT13Point5MinutesBefore7Point083Degrees; - public final Date getBainHashmashosRT2Stars; - public final Date getBainHashmashosYereim18Minutes; - public final Date getBainHashmashosYereim3Point05Degrees; - public final Date getBainHashmashosYereim16Point875Minutes; - public final Date getBainHashmashosYereim2Point8Degrees; - public final Date getBainHashmashosYereim13Point5Minutes; - public final Date getBainHashmashosYereim2Point1Degrees; - public final Date getTzaisGeonim3Point7Degrees; - public final Date getTzaisGeonim3Point8Degrees; - public final Date getTzaisGeonim5Point95Degrees; - public final Date getTzaisGeonim4Point61Degrees; - public final Date getTzaisGeonim4Point37Degrees; - public final Date getTzaisGeonim5Point88Degrees; - public final Date getTzaisGeonim4Point8Degrees; - public final Date getTzaisGeonim6Point45Degrees; - public final Date getTzaisGeonim7Point083Degrees; - public final Date getTzaisGeonim7Point67Degrees; - public final Date getTzaisGeonim8Point5Degrees; - public final Date getTzaisGeonim9Point3Degrees; - public final Date getTzaisGeonim9Point75Degrees; - public final Date getTzais60; - public final Date getTzaisAteretTorah; - public final Date getSofZmanShmaAteretTorah; - public final Date getSofZmanTfilahAteretTorah; - public final Date getMinchaGedolaAteretTorah; - public final Date getMinchaKetanaAteretTorah; - public final Date getPlagHaminchaAteretTorah; - public final Date getTzais72Zmanis; - public final Date getTzais90Zmanis; - public final Date getTzais96Zmanis; - public final Date getTzais90; - public final Date getTzais120; - public final Date getTzais120Zmanis; - public final Date getTzais16Point1Degrees; - public final Date getTzais26Degrees; - public final Date getTzais18Degrees; - public final Date getTzais19Point8Degrees; - public final Date getTzais96; - public final Date getFixedLocalChatzos; - public final Date getSofZmanKidushLevanaBetweenMoldos; - public final Date getSofZmanKidushLevana15Days; - public final Date getTchilasZmanKidushLevana3Days; - public final Date getZmanMolad; - public final Date getTchilasZmanKidushLevana7Days; - public final Date getSofZmanAchilasChametzGRA; - public final Date getSofZmanAchilasChametzMGA72Minutes; - public final Date getSofZmanAchilasChametzMGA16Point1Degrees; - public final Date getSofZmanBiurChametzGRA; - public final Date getSofZmanBiurChametzMGA72Minutes; - public final Date getSofZmanBiurChametzMGA16Point1Degrees; - public final Date getSolarMidnight; + public final Instant getPlagHamincha120MinutesZmanis; + public final Instant getPlagHamincha120Minutes; + public final Instant getAlos60; + public final Instant getAlos72Zmanis; + public final Instant getAlos96; + public final Instant getAlos90Zmanis; + public final Instant getAlos96Zmanis; + public final Instant getAlos90; + public final Instant getAlos120; + public final Instant getAlos120Zmanis; + public final Instant getAlos26Degrees; + public final Instant getAlos18Degrees; + public final Instant getAlos19Degrees; + public final Instant getAlos19Point8Degrees; + public final Instant getAlos16Point1Degrees; + public final Instant getMisheyakir11Point5Degrees; + public final Instant getMisheyakir11Degrees; + public final Instant getMisheyakir10Point2Degrees; + public final Instant getMisheyakir7Point65Degrees; + public final Instant getMisheyakir9Point5Degrees; + public final Instant getSofZmanShmaMGA19Point8Degrees; + public final Instant getSofZmanShmaMGA16Point1Degrees; + public final Instant getSofZmanShmaMGA18Degrees; + public final Instant getSofZmanShmaMGA72Minutes; + public final Instant getSofZmanShmaMGA72MinutesZmanis; + public final Instant getSofZmanShmaMGA90Minutes; + public final Instant getSofZmanShmaMGA90MinutesZmanis; + public final Instant getSofZmanShmaMGA96Minutes; + public final Instant getSofZmanShmaMGA96MinutesZmanis; + public final Instant getSofZmanShma3HoursBeforeChatzos; + public final Instant getSofZmanShmaMGA120Minutes; + public final Instant getSofZmanShmaAlos16Point1ToSunset; + public final Instant getSofZmanShmaAlos16Point1ToTzaisGeonim7Point083Degrees; + public final Instant getSofZmanTfilaMGA19Point8Degrees; + public final Instant getSofZmanTfilaMGA16Point1Degrees; + public final Instant getSofZmanTfilaMGA18Degrees; + public final Instant getSofZmanTfilaMGA72Minutes; + public final Instant getSofZmanTfilaMGA72MinutesZmanis; + public final Instant getSofZmanTfilaMGA90Minutes; + public final Instant getSofZmanTfilaMGA90MinutesZmanis; + public final Instant getSofZmanTfilaMGA96Minutes; + public final Instant getSofZmanTfilaMGA96MinutesZmanis; + public final Instant getSofZmanTfilaMGA120Minutes; + public final Instant getSofZmanTfila2HoursBeforeChatzos; + public final Instant getMinchaGedola30Minutes; + public final Instant getMinchaGedola72Minutes; + public final Instant getMinchaGedola16Point1Degrees; + public final Instant getMinchaGedolaAhavatShalom; + public final Instant getMinchaGedolaGreaterThan30; + public final Instant getMinchaKetana16Point1Degrees; + public final Instant getMinchaKetanaAhavatShalom; + public final Instant getMinchaKetana72Minutes; + public final Instant getPlagHamincha60Minutes; + public final Instant getPlagHamincha72Minutes; + public final Instant getPlagHamincha90Minutes; + public final Instant getPlagHamincha96Minutes; + public final Instant getPlagHamincha96MinutesZmanis; + public final Instant getPlagHamincha90MinutesZmanis; + public final Instant getPlagHamincha72MinutesZmanis; + public final Instant getPlagHamincha16Point1Degrees; + public final Instant getPlagHamincha19Point8Degrees; + public final Instant getPlagHamincha26Degrees; + public final Instant getPlagHamincha18Degrees; + public final Instant getPlagAlosToSunset; + public final Instant getPlagAlos16Point1ToTzaisGeonim7Point083Degrees; + public final Instant getPlagAhavatShalom; + public final Instant getBainHashmashosRT13Point24Degrees; + public final Instant getBainHashmashosRT58Point5Minutes; + public final Instant getBainHashmashosRT13Point5MinutesBefore7Point083Degrees; + public final Instant getBainHashmashosRT2Stars; + public final Instant getBainHashmashosYereim18Minutes; + public final Instant getBainHashmashosYereim3Point05Degrees; + public final Instant getBainHashmashosYereim16Point875Minutes; + public final Instant getBainHashmashosYereim2Point8Degrees; + public final Instant getBainHashmashosYereim13Point5Minutes; + public final Instant getBainHashmashosYereim2Point1Degrees; + public final Instant getTzaisGeonim3Point7Degrees; + public final Instant getTzaisGeonim3Point8Degrees; + public final Instant getTzaisGeonim5Point95Degrees; + public final Instant getTzaisGeonim4Point61Degrees; + public final Instant getTzaisGeonim4Point37Degrees; + public final Instant getTzaisGeonim5Point88Degrees; + public final Instant getTzaisGeonim4Point8Degrees; + public final Instant getTzaisGeonim6Point45Degrees; + public final Instant getTzaisGeonim7Point083Degrees; + public final Instant getTzaisGeonim7Point67Degrees; + public final Instant getTzaisGeonim8Point5Degrees; + public final Instant getTzaisGeonim9Point3Degrees; + public final Instant getTzaisGeonim9Point75Degrees; + public final Instant getTzais60; + public final Instant getTzaisAteretTorah; + public final Instant getSofZmanShmaAteretTorah; + public final Instant getSofZmanTfilahAteretTorah; + public final Instant getMinchaGedolaAteretTorah; + public final Instant getMinchaKetanaAteretTorah; + public final Instant getPlagHaminchaAteretTorah; + public final Instant getTzais72Zmanis; + public final Instant getTzais90Zmanis; + public final Instant getTzais96Zmanis; + public final Instant getTzais90; + public final Instant getTzais120; + public final Instant getTzais120Zmanis; + public final Instant getTzais16Point1Degrees; + public final Instant getTzais26Degrees; + public final Instant getTzais18Degrees; + public final Instant getTzais19Point8Degrees; + public final Instant getTzais96; + public final Instant getFixedLocalChatzos; + public final Instant getSofZmanKidushLevanaBetweenMoldos; + public final Instant getSofZmanKidushLevana15Days; + public final Instant getTchilasZmanKidushLevana3Days; + public final Instant getZmanMolad; + public final Instant getTchilasZmanKidushLevana7Days; + public final Instant getSofZmanAchilasChametzGRA; + public final Instant getSofZmanAchilasChametzMGA72Minutes; + public final Instant getSofZmanAchilasChametzMGA16Point1Degrees; + public final Instant getSofZmanBiurChametzGRA; + public final Instant getSofZmanBiurChametzMGA72Minutes; + public final Instant getSofZmanBiurChametzMGA16Point1Degrees; + public final Instant getSolarMidnight; public final long getShaahZmanisBaalHatanya; - public final Date getAlosBaalHatanya; - public final Date getSofZmanShmaBaalHatanya; - public final Date getSofZmanTfilaBaalHatanya; - public final Date getSofZmanAchilasChametzBaalHatanya; - public final Date getSofZmanBiurChametzBaalHatanya; - public final Date getMinchaGedolaBaalHatanya; - public final Date getMinchaGedolaBaalHatanyaGreaterThan30; - public final Date getMinchaKetanaBaalHatanya; - public final Date getPlagHaminchaBaalHatanya; - public final Date getTzaisBaalHatanya; - public final Date getSofZmanShmaMGA18DegreesToFixedLocalChatzos; - public final Date getSofZmanShmaMGA16Point1DegreesToFixedLocalChatzos; - public final Date getSofZmanShmaMGA90MinutesToFixedLocalChatzos; - public final Date getSofZmanShmaMGA72MinutesToFixedLocalChatzos; - public final Date getSofZmanShmaGRASunriseToFixedLocalChatzos; - public final Date getSofZmanTfilaGRASunriseToFixedLocalChatzos; - public final Date getMinchaGedolaGRAFixedLocalChatzos30Minutes; - public final Date getMinchaKetanaGRAFixedLocalChatzosToSunset; - public final Date getPlagHaminchaGRAFixedLocalChatzosToSunset; - public final Date getTzais50; - public final Date getSamuchLeMinchaKetanaGRA; - public final Date getSamuchLeMinchaKetana16Point1Degrees; - public final Date getSamuchLeMinchaKetana72Minutes; + public final Instant getAlosBaalHatanya; + public final Instant getSofZmanShmaBaalHatanya; + public final Instant getSofZmanTfilaBaalHatanya; + public final Instant getSofZmanAchilasChametzBaalHatanya; + public final Instant getSofZmanBiurChametzBaalHatanya; + public final Instant getMinchaGedolaBaalHatanya; + public final Instant getMinchaGedolaBaalHatanyaGreaterThan30; + public final Instant getMinchaKetanaBaalHatanya; + public final Instant getPlagHaminchaBaalHatanya; + public final Instant getTzaisBaalHatanya; + public final Instant getSofZmanShmaMGA18DegreesToFixedLocalChatzos; + public final Instant getSofZmanShmaMGA16Point1DegreesToFixedLocalChatzos; + public final Instant getSofZmanShmaMGA90MinutesToFixedLocalChatzos; + public final Instant getSofZmanShmaMGA72MinutesToFixedLocalChatzos; + public final Instant getSofZmanShmaGRASunriseToFixedLocalChatzos; + public final Instant getSofZmanTfilaGRASunriseToFixedLocalChatzos; + public final Instant getMinchaGedolaGRAFixedLocalChatzos30Minutes; + public final Instant getMinchaKetanaGRAFixedLocalChatzosToSunset; + public final Instant getPlagHaminchaGRAFixedLocalChatzosToSunset; + public final Instant getTzais50; + public final Instant getSamuchLeMinchaKetanaGRA; + public final Instant getSamuchLeMinchaKetana16Point1Degrees; + public final Instant getSamuchLeMinchaKetana72Minutes; } /*static class FullAstronomicalCalculator { - Date getSunrise - Date getSeaLevelSunrise - Date getBeginCivilTwilight - Date getBeginNauticalTwilight - Date getBeginAstronomicalTwilight - Date getSunset - Date getSeaLevelSunset - Date getEndCivilTwilight - Date getEndNauticalTwilight - Date getEndAstronomicalTwilight - Date getTimeOffset - Date getTimeOffset - Date getSunriseOffsetByDegrees - Date getSunsetOffsetByDegrees + Instant getSunrise + Instant getSeaLevelSunrise + Instant getBeginCivilTwilight + Instant getBeginNauticalTwilight + Instant getBeginAstronomicalTwilight + Instant getSunset + Instant getSeaLevelSunset + Instant getEndCivilTwilight + Instant getEndNauticalTwilight + Instant getEndAstronomicalTwilight + Instant getTimeOffset + Instant getTimeOffset + Instant getSunriseOffsetByDegrees + Instant getSunsetOffsetByDegrees double getUTCSunrise double getUTCSeaLevelSunrise double getUTCSunset double getUTCSeaLevelSunset long getTemporalHour long getTemporalHour - Date getSunTransit - Date getSunTransit - Date getDateFromTime + Instant getSunTransit + Instant getSunTransit + Instant getDateFromTime double getSunriseSolarDipFromOffset double getSunsetSolarDipFromOffset Calendar getAdjustedCalendar @@ -847,14 +849,14 @@ public String toString() { private final int dayOfOmer; private final boolean tishaBav; private final JewishDate molad; - private final Date moladAsDate; - private final Date tchilasZmanKidushLevana3Days; - private final Date tchilasZmanKidushLevana7Days; - private final Date sofZmanKidushLevanaBetweenMoldos; - private final Date sofZmanKidushLevana15Days; + private final Instant moladAsDate; + private final Instant tchilasZmanKidushLevana3Days; + private final Instant tchilasZmanKidushLevana7Days; + private final Instant sofZmanKidushLevanaBetweenMoldos; + private final Instant sofZmanKidushLevana15Days; private final int tekufasTishreiElapsedDays; - public FullCalendar(LocalDate current, JewishDate currentJewishDate, int yomTovIndex, Daf dafYomiBavli, Daf dafYomiYerushalmi, boolean isruChag, boolean birkasHachamah, JewishCalendar.Parsha parshah, JewishCalendar.Parsha upcomingParshah, JewishCalendar.Parsha specialShabbos, boolean yomTov, boolean yomTovAssurBemelacha, boolean assurBemelacha, boolean hasCandleLighting, boolean tomorrowShabbosOrYomTov, boolean erevYomTovSheni, boolean aseresYemeiTeshuva, boolean pesach, boolean cholHamoedPesach, boolean shavuos, boolean roshHashana, boolean yomKippur, boolean succos, boolean hoshanaRabba, boolean shminiAtzeres, boolean simchasTorah, boolean cholHamoedSuccos, boolean cholHamoed, boolean erevYomTov, boolean erevRoshChodesh, boolean yomKippurKatan, boolean beHaB, boolean taanis, boolean taanisBechoros, int dayOfChanukah, boolean chanukah, boolean purim, boolean roshChodesh, boolean macharChodesh, boolean shabbosMevorchim, int dayOfOmer, boolean tishaBav, JewishDate molad, Date moladAsDate, Date tchilasZmanKidushLevana3Days, Date tchilasZmanKidushLevana7Days, Date sofZmanKidushLevanaBetweenMoldos, Date sofZmanKidushLevana15Days, int tekufasTishreiElapsedDays) { + public FullCalendar(LocalDate current, JewishDate currentJewishDate, int yomTovIndex, Daf dafYomiBavli, Daf dafYomiYerushalmi, boolean isruChag, boolean birkasHachamah, JewishCalendar.Parsha parshah, JewishCalendar.Parsha upcomingParshah, JewishCalendar.Parsha specialShabbos, boolean yomTov, boolean yomTovAssurBemelacha, boolean assurBemelacha, boolean hasCandleLighting, boolean tomorrowShabbosOrYomTov, boolean erevYomTovSheni, boolean aseresYemeiTeshuva, boolean pesach, boolean cholHamoedPesach, boolean shavuos, boolean roshHashana, boolean yomKippur, boolean succos, boolean hoshanaRabba, boolean shminiAtzeres, boolean simchasTorah, boolean cholHamoedSuccos, boolean cholHamoed, boolean erevYomTov, boolean erevRoshChodesh, boolean yomKippurKatan, boolean beHaB, boolean taanis, boolean taanisBechoros, int dayOfChanukah, boolean chanukah, boolean purim, boolean roshChodesh, boolean macharChodesh, boolean shabbosMevorchim, int dayOfOmer, boolean tishaBav, JewishDate molad, Instant moladAsDate, Instant tchilasZmanKidushLevana3Days, Instant tchilasZmanKidushLevana7Days, Instant sofZmanKidushLevanaBetweenMoldos, Instant sofZmanKidushLevana15Days, int tekufasTishreiElapsedDays) { this.current = current; this.currentJewishDate = currentJewishDate; this.yomTovIndex = yomTovIndex; diff --git a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_DaysInGregorianMonth.java b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_DaysInGregorianMonth.java deleted file mode 100644 index 4dd5ac87..00000000 --- a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_DaysInGregorianMonth.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2011. Jay R. Gindin - */ - -package com.kosherjava.zmanim.hebrewcalendar; - -import org.junit.*; - -import java.util.Calendar; - -/** - * Verify the calculation of the number of days in a month. Not too hard...just the rules about when February - * has 28 or 29 days... - */ -@SuppressWarnings({ "MagicNumber" }) -public class UT_DaysInGregorianMonth { - - - @Test - public void testDaysInMonth() { - - JewishDate hebrewDate = new JewishDate(); - - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, 2011); - cal.set(Calendar.MONTH, Calendar.JANUARY); - hebrewDate.setDate(cal); - - assertDaysInMonth(false, hebrewDate); - } - - - - @Test - public void testDaysInMonthLeapYear() { - - JewishDate hebrewDate = new JewishDate(); - - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, 2012); - cal.set(Calendar.MONTH, Calendar.JANUARY); - hebrewDate.setDate(cal); - - assertDaysInMonth(true, hebrewDate); - } - - - @Test - public void testDaysInMonth100Year() { - - JewishDate hebrewDate = new JewishDate(); - - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, 2100); - cal.set(Calendar.MONTH, Calendar.JANUARY); - hebrewDate.setDate(cal); - - assertDaysInMonth(false, hebrewDate); - } - - - @Test - public void testDaysInMonth400Year() { - - JewishDate hebrewDate = new JewishDate(); - - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, 2000); - cal.set(Calendar.MONTH, Calendar.JANUARY); - hebrewDate.setDate(cal); - - assertDaysInMonth(true, hebrewDate); - } - - - private void assertDaysInMonth( - boolean febIsLeap, - JewishDate hebrewDate - ) { - - Assert.assertEquals(31, hebrewDate.getLastDayOfGregorianMonth(1)); - Assert.assertEquals(febIsLeap ? 29 : 28, hebrewDate.getLastDayOfGregorianMonth(2)); - Assert.assertEquals(31, hebrewDate.getLastDayOfGregorianMonth(3)); - Assert.assertEquals(30, hebrewDate.getLastDayOfGregorianMonth(4)); - Assert.assertEquals(31, hebrewDate.getLastDayOfGregorianMonth(5)); - Assert.assertEquals(30, hebrewDate.getLastDayOfGregorianMonth(6)); - Assert.assertEquals(31, hebrewDate.getLastDayOfGregorianMonth(7)); - Assert.assertEquals(31, hebrewDate.getLastDayOfGregorianMonth(8)); - Assert.assertEquals(30, hebrewDate.getLastDayOfGregorianMonth(9)); - Assert.assertEquals(31, hebrewDate.getLastDayOfGregorianMonth(10)); - Assert.assertEquals(30, hebrewDate.getLastDayOfGregorianMonth(11)); - Assert.assertEquals(31, hebrewDate.getLastDayOfGregorianMonth(12)); - } - - -} // End of UT_DaysInGregorianMonth class diff --git a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_GregorianDateNavigation.java b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_GregorianDateNavigation.java index 6feb7e38..1b53934a 100644 --- a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_GregorianDateNavigation.java +++ b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_GregorianDateNavigation.java @@ -6,7 +6,8 @@ import org.junit.*; -import java.util.Calendar; +import java.time.LocalDate; +import java.time.Month; /** * Checks that we can roll forward & backward the gregorian dates... @@ -17,125 +18,111 @@ public class UT_GregorianDateNavigation { @Test public void gregorianForwardMonthToMonth() { - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, 2011); - cal.set(Calendar.MONTH, Calendar.JANUARY); - cal.set(Calendar.DATE, 31); + LocalDate localDate = LocalDate.of(2011, Month.JANUARY,31); - JewishDate hebrewDate = new JewishDate(cal); + JewishDate hebrewDate = new JewishDate(localDate); Assert.assertEquals(5771, hebrewDate.getJewishYear()); Assert.assertEquals(11, hebrewDate.getJewishMonth()); Assert.assertEquals(26, hebrewDate.getJewishDayOfMonth()); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(1, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + hebrewDate.addDays(1); + Assert.assertEquals(2, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(11, hebrewDate.getJewishMonth()); Assert.assertEquals(27, hebrewDate.getJewishDayOfMonth()); - - cal.set(Calendar.MONTH, Calendar.FEBRUARY); - cal.set(Calendar.DATE, 28); - hebrewDate.setDate(cal); - Assert.assertEquals(1, hebrewDate.getGregorianMonth()); - Assert.assertEquals(28, hebrewDate.getGregorianDayOfMonth()); + + localDate = LocalDate.of(2011, Month.FEBRUARY,28); + hebrewDate = new JewishDate(localDate); + Assert.assertEquals(2, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(28, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(12, hebrewDate.getJewishMonth()); Assert.assertEquals(24, hebrewDate.getJewishDayOfMonth()); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(2, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + hebrewDate.addDays(1); + Assert.assertEquals(3, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(12, hebrewDate.getJewishMonth()); Assert.assertEquals(25, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.MARCH); - cal.set(Calendar.DATE, 31); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(3, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.MARCH,31); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(4, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(13, hebrewDate.getJewishMonth()); Assert.assertEquals(26, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.APRIL); - cal.set(Calendar.DATE, 30); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(4, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.APRIL,30); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(5, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(1, hebrewDate.getJewishMonth()); Assert.assertEquals(27, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.MAY); - cal.set(Calendar.DATE, 31); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(5, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.MAY,31); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(6, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(2, hebrewDate.getJewishMonth()); Assert.assertEquals(28, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.JUNE); - cal.set(Calendar.DATE, 30); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(6, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.JUNE,30); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(7, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(3, hebrewDate.getJewishMonth()); Assert.assertEquals(29, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.JULY); - cal.set(Calendar.DATE, 31); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(7, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.JULY,31); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(8, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(5, hebrewDate.getJewishMonth()); Assert.assertEquals(1, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.AUGUST); - cal.set(Calendar.DATE, 31); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(8, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.AUGUST,31); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(9, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(6, hebrewDate.getJewishMonth()); Assert.assertEquals(2, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.SEPTEMBER); - cal.set(Calendar.DATE, 30); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(9, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.SEPTEMBER,30); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(10, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(7, hebrewDate.getJewishMonth()); Assert.assertEquals(3, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.OCTOBER); - cal.set(Calendar.DATE, 31); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(10, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.OCTOBER,31); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(11, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(5772, hebrewDate.getJewishYear()); Assert.assertEquals(8, hebrewDate.getJewishMonth()); Assert.assertEquals(4, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.NOVEMBER); - cal.set(Calendar.DATE, 30); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(11, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.NOVEMBER,30); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(12, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(9, hebrewDate.getJewishMonth()); Assert.assertEquals(5, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.MONTH, Calendar.DECEMBER); - cal.set(Calendar.DATE, 31); - hebrewDate.setDate(cal); - hebrewDate.forward(Calendar.DATE, 1); - Assert.assertEquals(2012, hebrewDate.getGregorianYear()); - Assert.assertEquals(0, hebrewDate.getGregorianMonth()); - Assert.assertEquals(1, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2011, Month.DECEMBER,31); + hebrewDate = new JewishDate(localDate); + hebrewDate.addDays(1); + Assert.assertEquals(2012, hebrewDate.getLocalDate().getYear()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(1, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(10, hebrewDate.getJewishMonth()); Assert.assertEquals(6, hebrewDate.getJewishDayOfMonth()); } @@ -144,117 +131,101 @@ public void gregorianForwardMonthToMonth() { @Test public void gregorianBackwardMonthToMonth() { - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, 2011); - cal.set(Calendar.MONTH, Calendar.JANUARY); - cal.set(Calendar.DATE, 1); - - JewishDate hebrewDate = new JewishDate(cal); - hebrewDate.back(); - Assert.assertEquals(2010, hebrewDate.getGregorianYear()); - Assert.assertEquals(11, hebrewDate.getGregorianMonth()); - Assert.assertEquals(31, hebrewDate.getGregorianDayOfMonth()); + LocalDate localDate = LocalDate.of(2011, Month.JANUARY, 1); + JewishDate hebrewDate = new JewishDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(2010, hebrewDate.getLocalDate().getYear()); + Assert.assertEquals(12, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(31, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(10, hebrewDate.getJewishMonth()); Assert.assertEquals(24, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.DECEMBER); - cal.set(Calendar.YEAR, 2010); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(10, hebrewDate.getGregorianMonth()); - Assert.assertEquals(30, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.DECEMBER, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(11, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(30, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(9, hebrewDate.getJewishMonth()); Assert.assertEquals(23, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.NOVEMBER); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(9, hebrewDate.getGregorianMonth()); - Assert.assertEquals(31, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.NOVEMBER, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(10, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(31, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(8, hebrewDate.getJewishMonth()); Assert.assertEquals(23, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.OCTOBER); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(8, hebrewDate.getGregorianMonth()); - Assert.assertEquals(30, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.OCTOBER, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(9, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(30, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(7, hebrewDate.getJewishMonth()); Assert.assertEquals(22, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.SEPTEMBER); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(7, hebrewDate.getGregorianMonth()); - Assert.assertEquals(31, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.SEPTEMBER, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(8, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(31, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(5770, hebrewDate.getJewishYear()); Assert.assertEquals(6, hebrewDate.getJewishMonth()); Assert.assertEquals(21, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.AUGUST); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(6, hebrewDate.getGregorianMonth()); - Assert.assertEquals(31, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.AUGUST, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(7, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(31, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(5, hebrewDate.getJewishMonth()); Assert.assertEquals(20, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.JULY); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(5, hebrewDate.getGregorianMonth()); - Assert.assertEquals(30, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.JULY, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(6, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(30, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(4, hebrewDate.getJewishMonth()); Assert.assertEquals(18, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.JUNE); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(4, hebrewDate.getGregorianMonth()); - Assert.assertEquals(31, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.JUNE, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(5, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(31, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(3, hebrewDate.getJewishMonth()); Assert.assertEquals(18, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.MAY); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(3, hebrewDate.getGregorianMonth()); - Assert.assertEquals(30, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.MAY, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(4, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(30, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(2, hebrewDate.getJewishMonth()); Assert.assertEquals(16, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.APRIL); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(2, hebrewDate.getGregorianMonth()); - Assert.assertEquals(31, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.APRIL, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(3, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(31, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(1, hebrewDate.getJewishMonth()); Assert.assertEquals(16, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.MARCH); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(1, hebrewDate.getGregorianMonth()); - Assert.assertEquals(28, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.MARCH, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(2, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(28, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(12, hebrewDate.getJewishMonth()); Assert.assertEquals(14, hebrewDate.getJewishDayOfMonth()); - cal.set(Calendar.DATE, 1); - cal.set(Calendar.MONTH, Calendar.FEBRUARY); - hebrewDate.setDate(cal); - hebrewDate.back(); - Assert.assertEquals(0, hebrewDate.getGregorianMonth()); - Assert.assertEquals(31, hebrewDate.getGregorianDayOfMonth()); + localDate = LocalDate.of(2010, Month.FEBRUARY, 1); + hebrewDate.setGregorianDate(localDate); + hebrewDate.minusDays(1); + Assert.assertEquals(1, hebrewDate.getLocalDate().getMonthValue()); + Assert.assertEquals(31, hebrewDate.getLocalDate().getDayOfMonth()); Assert.assertEquals(11, hebrewDate.getJewishMonth()); Assert.assertEquals(16, hebrewDate.getJewishDayOfMonth()); diff --git a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_JewishDateNavigation.java b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_JewishDateNavigation.java index 2a0d6e66..eb177267 100644 --- a/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_JewishDateNavigation.java +++ b/src/test/java/com/kosherjava/zmanim/hebrewcalendar/UT_JewishDateNavigation.java @@ -6,6 +6,7 @@ import org.junit.*; +import java.time.LocalDate; import java.util.Calendar; /** @@ -20,9 +21,10 @@ public void jewishForwardMonthToMonth() { JewishDate jewishDate = new JewishDate(); jewishDate.setJewishDate(5771, 1, 1); - Assert.assertEquals(5, jewishDate.getGregorianDayOfMonth()); - Assert.assertEquals(3, jewishDate.getGregorianMonth()); - Assert.assertEquals(2011, jewishDate.getGregorianYear()); + LocalDate localDate = jewishDate.getLocalDate(); + Assert.assertEquals(5, localDate.getDayOfMonth()); + Assert.assertEquals(3, localDate.getMonthValue()); + Assert.assertEquals(2011, localDate.getYear()); } @@ -33,9 +35,28 @@ public void computeRoshHashana5771() { JewishDate jewishDate = new JewishDate(); jewishDate.setJewishDate(5771, 7, 1); - Assert.assertEquals(9, jewishDate.getGregorianDayOfMonth()); - Assert.assertEquals(8, jewishDate.getGregorianMonth()); - Assert.assertEquals(2010, jewishDate.getGregorianYear()); + LocalDate localDate = jewishDate.getLocalDate(); + Assert.assertEquals(9, localDate.getDayOfMonth()); + Assert.assertEquals(8, localDate.getMonthValue()); + Assert.assertEquals(2010, localDate.getYear()); + } + + @Test + public void addYearsUsesConfiguredAdarMonthWhenMovingToLeapYear() { + + JewishDate adarAlephDate = new JewishDate(); + adarAlephDate.setJewishDate(5783, JewishDate.ADAR, 10); + adarAlephDate.addYears(1, true); + Assert.assertEquals(5784, adarAlephDate.getJewishYear()); + Assert.assertEquals(JewishDate.ADAR, adarAlephDate.getJewishMonth()); + Assert.assertEquals(10, adarAlephDate.getJewishDayOfMonth()); + + JewishDate adarBeisDate = new JewishDate(); + adarBeisDate.setJewishDate(5783, JewishDate.ADAR, 10); + adarBeisDate.addYears(1, false); + Assert.assertEquals(5784, adarBeisDate.getJewishYear()); + Assert.assertEquals(JewishDate.ADAR_II, adarBeisDate.getJewishMonth()); + Assert.assertEquals(10, adarBeisDate.getJewishDayOfMonth()); }