Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishDate.java
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ private static int getLastDayOfGregorianMonth(int year, int month) {
* @return the {@code LocalDate}.
*/
private static LocalDate absDateToDate(int absDate) {
int year = absDate / 366; // Search forward year by year from approximate year
int year = Math.floorDiv(absDate, 366); // Search forward year by year from approximate year
while (absDate >= gregorianDateToAbsDate(year + 1, 1, 1)) {
year++;
}
Expand Down Expand Up @@ -347,11 +347,12 @@ private static int gregorianDateToAbsDate(int year, int month, int dayOfMonth) {
}

int y = year - 1;
// Floor division, so that year 0, a leap year, gets its leap day
return (absDate // days this year
+ 365 * y // days in previous years ignoring leap days
+ y / 4 // Julian leap days before this year
- y / 100 // minus prior century years
+ y / 400); // plus prior years divisible by 400
+ Math.floorDiv(y, 4) // Julian leap days before this year
- Math.floorDiv(y, 100) // minus prior century years
+ Math.floorDiv(y, 400)); // plus prior years divisible by 400
}

/**
Expand Down Expand Up @@ -670,13 +671,11 @@ public int getDaysInJewishMonth() {
}

/**
* Computes and sets the Jewish date fields based on the provided absolute (Gregorian) date.
* Computes and sets the Jewish date fields based on the provided absolute (Gregorian) date. The date may be before
* January 1, 0001, as the <em>molad</em> of Teves 3761 is, on December 12, 0000.
* @param gregorianAbsDate the Gregorian absolute date.
*/
private synchronized 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;
Expand All @@ -696,8 +695,8 @@ private synchronized void setAbsDate(int gregorianAbsDate) {
// 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;
// day of week, with floorMod so that a date before January 1, 0001 gets the right day
dayOfWeek = Math.floorMod(gregorianAbsDate, 7) + 1;
}

/**
Expand Down Expand Up @@ -855,6 +854,9 @@ public void setGregorianDate(ZonedDateTime zonedDateTime) {
*/
public void setGregorianDate(LocalDate localDate) {
int absDate = gregorianDateToAbsDate(localDate.getYear(), localDate.getMonth().getValue(), localDate.getDayOfMonth());
if (absDate <= 0) {
throw new IllegalArgumentException("Dates in the BC era are not supported");
}
setAbsDate(absDate); // convert to Jewish date
}

Expand Down Expand Up @@ -975,7 +977,11 @@ public void minusDays(int days){
if (days < 1) {
throw new IllegalArgumentException("The number of days to subtract must be greater than zero.");
}
setAbsDate(getAbsDate() - days);
int absDate = getAbsDate() - days;
if (absDate <= 0) {
throw new IllegalArgumentException("Dates in the BC era are not supported");
}
setAbsDate(absDate);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,15 @@ private static int getNumOfSpecialDays(LocalDate start, LocalDate end) {


/**
* Checks if a date is after start and on or before end.
* Checks if a date is on or after start and on or before end. A cycle can start on, or be extended to start
* on, Yom Kippur or Tisha B'Av, so the start day is counted.
* @param start the start <code>ZonedDateTime</code>
* @param date the <code>ZonedDateTime</code> to check
* @param end the end <code>ZonedDateTime</code>
* @return if the date is between the two dates
*/
private static boolean isBetween(LocalDate start, LocalDate date, LocalDate end) {
return start.isBefore(date) && !end.isBefore(date);
return !date.isBefore(start) && !end.isBefore(date);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,18 @@ public void addYearsUsesConfiguredAdarMonthWhenMovingToLeapYear() {
Assert.assertEquals(10, adarBeisDate.getJewishDayOfMonth());
}

/**
* The molad of Teves 3761 is Tuesday 12 December of Gregorian year 0, which is a leap year.
*/
@Test
public void moladInGregorianYear0() {
JewishDate molad = new JewishDate(3761, JewishDate.TEVES, 20).getMolad();
Assert.assertEquals(LocalDate.of(0, 12, 12), molad.getLocalDate());
Assert.assertEquals(Calendar.TUESDAY, molad.getDayOfWeek());
Assert.assertEquals(20, molad.getMoladHours());
Assert.assertEquals(7, molad.getMoladMinutes());
Assert.assertEquals(2, molad.getMoladChalakim());
}


} // End of UT_JewishDateNavigation class
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.kosherjava.zmanim.hebrewcalendar;

import java.time.LocalDate;
import java.util.Calendar;

import org.junit.*;
Expand Down Expand Up @@ -50,4 +51,33 @@ public void testCorrectSpecialDate() {
System.out.println(hdf.formatDafYomiYerushalmi(jewishCalendar.getDafYomiYerushalmi()));
}

/**
* The cycle ending in 2172 is extended for Tisha B'Av 5932. It still has every daf, ending with Niddah 13 on
* 7 August 2172.
*/
@Test
public void testCycleExtendedForTishaBav() {
assertDaf(LocalDate.of(2172, 8, 6), 38, 12);
assertDaf(LocalDate.of(2172, 8, 7), 38, 13);
assertDaf(LocalDate.of(2172, 8, 8), 0, 1);
}

/**
* Tisha B'Av 6240 falls the day before the last daf of a cycle. The cycle still has every daf, ending with
* Niddah 13 on 16 August 2480, and the next one starts with Berachos 1.
*/
@Test
public void testCycleWithTishaBavBeforeItsLastDaf() {
assertDaf(LocalDate.of(2480, 8, 14), 38, 12);
Assert.assertNull(new JewishCalendar(LocalDate.of(2480, 8, 15)).getDafYomiYerushalmi());
assertDaf(LocalDate.of(2480, 8, 16), 38, 13);
assertDaf(LocalDate.of(2480, 8, 17), 0, 1);
}

private static void assertDaf(LocalDate date, int masechtaNumber, int daf) {
Daf dafYomi = new JewishCalendar(date).getDafYomiYerushalmi();
Assert.assertEquals(date.toString(), masechtaNumber, dafYomi.getMasechtaNumber());
Assert.assertEquals(date.toString(), daf, dafYomi.getDaf());
}

}
Loading