diff --git a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/HebrewDateFormatter.java b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/HebrewDateFormatter.java index a46e47c1..e4715b2a 100644 --- a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/HebrewDateFormatter.java +++ b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/HebrewDateFormatter.java @@ -404,6 +404,9 @@ public void setTransliteratedHolidayList(String[] transliteratedHolidays) { "שושן פורים קטן", "אסרו חג"}; + private final String[] tekufaNames = new String[] {"Tishrei", "Teves", "Nissan", "Tammuz"}; + + private final String[] hebrewTekufaNames = new String[] {"תשרי", "טבת", "ניסן", "תמוז"}; /** * Formats the Yom Tov (holiday) in Hebrew or transliterated Latin characters. * @@ -1008,4 +1011,24 @@ public String formatSpecialParsha(JewishCalendar jewishCalendar) { JewishCalendar.Parsha specialParsha = jewishCalendar.getSpecialShabbos(); return hebrewFormat ? hebrewParshaMap.get(specialParsha) : transliteratedParshaMap.get(specialParsha); } + + /** + * Returns a string if the current day has a tekufa event. The string will contain the name of the tekufa/season that is arriving. + * If this method is called on a day without a tekufa event, it will return an empty string. + * @return a string with the name of the upcoming tekufa/season, which could be: "Tishrei", "Teves", "Nissan", "Tammuz", + * or an empty string on a day without a tekufa event. + */ + public String formatTekufaName(JewishCalendar jewishCalendar) { + double INITIAL_TEKUFA_OFFSET = 12.625; // the number of days Tekufas Tishrei occurs before JEWISH_EPOCH + double days = JewishDate.getJewishCalendarElapsedDays(jewishCalendar.getJewishYear()) + jewishCalendar.getDaysSinceStartOfJewishYear() + INITIAL_TEKUFA_OFFSET - 1; // total days since first Tekufas Tishrei event + + double solarDaysElapsed = days % 365.25; // total days elapsed since start of solar year + int currentTekufaNumber = (int) (solarDaysElapsed / 91.3125); // the current quarter of the solar year + double tekufaDaysElapsed = solarDaysElapsed % 91.3125; // the number of days that have passed since a tekufa event + if (tekufaDaysElapsed > 0 && tekufaDaysElapsed <= 1) { // if the tekufa happens in the upcoming 24 hours + return isHebrewFormat() ? "תקופת " + hebrewTekufaNames[currentTekufaNumber] : "Tekufas " + tekufaNames[currentTekufaNumber];//0 for Tishrei, 1 for Tevet, 2, for Nissan, 3 for Tammuz + } else { + return ""; + } + } } diff --git a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishCalendar.java b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishCalendar.java index 2d0458bf..a67fb95a 100644 --- a/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishCalendar.java +++ b/src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishCalendar.java @@ -1379,6 +1379,62 @@ public int getTekufasTishreiElapsedDays() { double solar = (getJewishYear() - 1) * 365.25; return (int) Math.floor(days - solar); } + + /** + * Returns a Double that represents the hours for when the Tekufa (season) changes. There are 4 tekufas + * a year: Nissan/Spring, Tammuz/Summer, Tishri/Fall, and Tevet/Winter. This calculation is according to Shmuel + * in Eruvin 56a, which is a more rounded up version of Rav Adda's calculation. The Rama writes in Yoreh De'ah 116:5 + * that one should not drink water during the tekufa change. Rabbi Ovadia Yosef (Halichot Olam, Chelek 7, Page 183) + * recommends to abstain from drinking water for a range of 1 hour. (30 minutes before and after the tekufa event) + * + * @return the number of hours into the hebrew day that the tekufa (season) change takes place, or null if the + * tekufa does not occur on current day. For example: 19.5 would mean that the tekufa occurs 19 hours and a half into + * the hebrew date, or 13 and a half hours (-6 hours) into the Gregorian date. + */ + public Double getTekufa() { + double INITIAL_TEKUFA_OFFSET = 12.625; // the number of days Tekufas Tishrei occurs before JEWISH_EPOCH + + double days = getJewishCalendarElapsedDays(getJewishYear()) + getDaysSinceStartOfJewishYear() + INITIAL_TEKUFA_OFFSET - 1; // total days since first Tekufas Tishrei event + + double solarDaysElapsed = days % 365.25; // total days elapsed since start of solar year + double tekufaDaysElapsed = solarDaysElapsed % 91.3125; // the number of days that have passed since a tekufa event + if (tekufaDaysElapsed > 0 && tekufaDaysElapsed <= 1) { // if the tekufa happens in the upcoming 24 hours + return ((1.0 - tekufaDaysElapsed) * 24.0) % 24;// rationalize the tekufa event to number of hours since start of jewish day + } else { + return null; + } + } + + /** + * Returns a Instant if the current day has a tekufa (season) change. The Instant will contain the time that the tekufa (season) + * is arriving. If this method is called on a day without a tekufa change, it will return a null. + * The default implementation of this method will return the Tekufa change according to the calculations of Rabbi + * Tulchinsky in his calendar Luach Itim + * Lebinah. However, there is also the opinion of Rabbi Yonah Boron, who says to calculate + * the tekufa based on local midday in Israel which causes a 21-minute difference. There is a third opinion as well + * to use seasonal midday but that is not a generally followed opinion, so it has not been implemented. + * @param shouldMinus21Minutes if true, removes 21 minutes from the time of Rabbi Tulchinsky's tekufa which will + * result to the opinion of Rabbi Yonah Boron. + * @return an Instant with the time that the tekufa (season) changes or a null on a day with no tekufa change. + */ + public Instant getTekufaAsInstant(boolean shouldMinus21Minutes) { + Double hours = getTekufa(); + if (hours == null) { + return null; + } + // The tekufa Date (point in time) must be generated using standard time. Using "Asia/Jerusalem" timezone will result in the time + // being incorrectly off by an hour in the summer due to DST. Proper adjustment for the actual time in DST will be done by the date + // formatter class used to display the Date. + ZoneId yerushalayimStandardTZ = ZoneId.of("GMT+2"); + + hours = hours - 6; // minus 6 hours because the hebrew date starts at sunset which is at 6PM + int minutes = (int) ((hours - hours.intValue()) * 60); + + LocalTime time = LocalTime.of(hours.intValue(), minutes); + ZonedDateTime tekufaZDT = ZonedDateTime.of(getLocalDate(), time, yerushalayimStandardTZ); + + return tekufaZDT.minusMinutes(shouldMinus21Minutes ? 21 : 0).toInstant(); + } /** * Returns true if the current day is Isru Chag. The method returns true for the day following Pesach