Skip to content

Commit 8b9dba0

Browse files
authored
Start using java.time classes
1 parent d103d3d commit 8b9dba0

1 file changed

Lines changed: 134 additions & 148 deletions

File tree

src/main/java/com/kosherjava/zmanim/hebrewcalendar/YerushalmiYomiCalculator.java

Lines changed: 134 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
*/
1616
package com.kosherjava.zmanim.hebrewcalendar;
1717

18-
import java.util.Calendar;
19-
import java.util.GregorianCalendar;
20-
18+
import java.time.ZoneId;
19+
import java.time.ZonedDateTime;
2120

2221
/**
2322
* This class calculates the <a href="https://en.wikipedia.org/wiki/Jerusalem_Talmud">Talmud Yerusalmi</a> <a href=
@@ -27,149 +26,136 @@
2726
* @author &copy; Eliyahu Hershfeld 2017 - 2025
2827
*/
2928
public class YerushalmiYomiCalculator {
30-
31-
/**
32-
* The start date of the first Daf Yomi Yerushalmi cycle of February 2, 1980 / 15 Shevat, 5740.
33-
*/
34-
private final static Calendar DAF_YOMI_START_DAY = new GregorianCalendar(1980, Calendar.FEBRUARY, 2);
35-
/** The number of milliseconds in a day. */
36-
private final static int DAY_MILIS = 1000 * 60 * 60 * 24;
37-
/** The number of pages in the Talmud Yerushalmi.*/
38-
private final static int WHOLE_SHAS_DAFS = 1554;
39-
/** The number of pages per <em>masechta</em> (tractate).*/
40-
private final static int[] BLATT_PER_MASECHTA = {
41-
68, 37, 34, 44, 31, 59, 26, 33, 28, 20, 13, 92, 65, 71, 22, 22, 42, 26, 26, 33, 34, 22,
42-
19, 85, 72, 47, 40, 47, 54, 48, 44, 37, 34, 44, 9, 57, 37, 19, 13};
43-
44-
/**
45-
* Default constructor.
46-
*/
47-
public YerushalmiYomiCalculator() {
48-
// nothing here
49-
}
50-
51-
/**
52-
* Returns the <a href="https://en.wikipedia.org/wiki/Daf_Yomi">Daf Yomi</a>
53-
* <a href="https://en.wikipedia.org/wiki/Jerusalem_Talmud">Yerusalmi</a> page ({@link Daf}) for a given date.
54-
* The first Daf Yomi cycle started on 15 Shevat (Tu Bishvat), 5740 (February, 2, 1980) and calculations
55-
* prior to this date will result in an IllegalArgumentException thrown. A null will be returned on Tisha B'Av or
56-
* Yom Kippur.
57-
*
58-
* @param calendar
59-
* the calendar date for calculation
60-
* @return the {@link Daf} or null if the date is on Tisha B'Av or Yom Kippur.
61-
*
62-
* @throws IllegalArgumentException
63-
* if the date is prior to the February 2, 1980, the start of the first Daf Yomi Yerushalmi cycle
64-
*/
65-
public static Daf getDafYomiYerushalmi(JewishCalendar calendar) {
66-
67-
Calendar nextCycle = new GregorianCalendar();
68-
Calendar prevCycle = new GregorianCalendar();
69-
Calendar requested = calendar.getGregorianCalendar();
70-
int masechta = 0;
71-
Daf dafYomi = null;
72-
73-
// There isn't Daf Yomi on Yom Kippur or Tisha B'Av.
74-
if ( calendar.getYomTovIndex() == JewishCalendar.YOM_KIPPUR ||
75-
calendar.getYomTovIndex() == JewishCalendar.TISHA_BEAV ) {
76-
return null;
77-
}
78-
79-
80-
if (requested.before(DAF_YOMI_START_DAY)) {
81-
throw new IllegalArgumentException(requested + " is prior to organized Daf Yomi Yerushalmi cycles that started on "
82-
+ DAF_YOMI_START_DAY);
83-
}
84-
85-
// Start to calculate current cycle. init the start day
86-
nextCycle.setTime(DAF_YOMI_START_DAY.getTime());
87-
88-
// Go cycle by cycle, until we get the next cycle
89-
while (requested.after(nextCycle)) {
90-
prevCycle.setTime(nextCycle.getTime());
91-
92-
// Adds the number of whole shas dafs. and the number of days that not have daf.
93-
nextCycle.add(Calendar.DAY_OF_MONTH, WHOLE_SHAS_DAFS);
94-
nextCycle.add(Calendar.DAY_OF_MONTH, getNumOfSpecialDays(prevCycle, nextCycle));
95-
}
96-
97-
// Get the number of days from cycle start until request.
98-
int dafNo = (int)(getDiffBetweenDays(prevCycle, requested));
99-
100-
// Get the number of special day to subtract
101-
int specialDays = getNumOfSpecialDays(prevCycle, requested);
102-
int total = dafNo - specialDays;
103-
104-
// Finally find the daf.
105-
for (int i : BLATT_PER_MASECHTA) {
106-
if (total < i) {
107-
dafYomi = new Daf(masechta, total + 1);
108-
break;
109-
}
110-
total -= i;
111-
masechta++;
112-
}
113-
114-
return dafYomi;
115-
}
116-
117-
/**
118-
* Return the number of special days (Yom Kippur and Tisha Beav, where there are no dafim), between the start date
119-
* (as a <code>Calendar</code>) and end date (also as a <code>Calendar</code>).
120-
*
121-
* @param start date to start calculating from
122-
* @param end date to finish calculating at
123-
* @return the number of special days between the start and end dates
124-
*/
125-
private static int getNumOfSpecialDays(Calendar start, Calendar end) {
126-
127-
// Find the start and end Jewish years
128-
int startYear = new JewishCalendar(start).getJewishYear();
129-
int endYear = new JewishCalendar(end).getJewishYear();
130-
131-
// Value to return
132-
int specialDays = 0;
133-
134-
//Instant of special Dates
135-
JewishCalendar yom_kippur = new JewishCalendar(5770, 7, 10);
136-
JewishCalendar tisha_beav = new JewishCalendar(5770, 5, 9);
137-
138-
// Go over the years and find special dates
139-
for (int i = startYear; i <= endYear; i++) {
140-
yom_kippur.setJewishYear(i);
141-
tisha_beav.setJewishYear(i);
142-
143-
if (isBetween(start, yom_kippur.getGregorianCalendar(), end)) {
144-
specialDays++;
145-
}
146-
if (isBetween(start, tisha_beav.getGregorianCalendar(), end)) {
147-
specialDays++;
148-
}
149-
}
150-
151-
return specialDays;
152-
}
153-
154-
/**
155-
* Return if the date is between two dates
156-
*
157-
* @param start the start date
158-
* @param date the date being compared
159-
* @param end the end date
160-
* @return if the date is between the start and end dates
161-
*/
162-
private static boolean isBetween(Calendar start, Calendar date, Calendar end ) {
163-
return start.before(date) && end.after(date);
164-
}
165-
166-
/**
167-
* Return the number of days between the dates passed in
168-
* @param start the start date
169-
* @param end the end date
170-
* @return the number of days between the start and end dates
171-
*/
172-
private static long getDiffBetweenDays(Calendar start, Calendar end) {
173-
return (end.getTimeInMillis() - start.getTimeInMillis()) / DAY_MILIS;
174-
}
29+
30+
/** Start date of first Daf Yomi Yerushalmi cycle: 1980-02-02 */
31+
private static final ZonedDateTime DAF_YOMI_START_DAY =
32+
ZonedDateTime.of(1980, 2, 2, 0, 0, 0, 0, ZoneId.systemDefault());
33+
34+
/** milliseconds in a day*/
35+
private static final int DAY_MILLIS = 1000 * 60 * 60 * 24;
36+
/** number of pages (<em>blatt/dafim</em>) in <em>Shas</em>*/
37+
private static final int WHOLE_SHAS_DAFS = 1554;
38+
39+
/** number of pages (<em>blatt/dafim</em>) per <em>masechta</em>*/
40+
private static final int[] BLATT_PER_MASECHTA = {
41+
68, 37, 34, 44, 31, 59, 26, 33, 28, 20, 13, 92, 65, 71, 22, 22, 42, 26, 26, 33, 34, 22,
42+
19, 85, 72, 47, 40, 47, 54, 48, 44, 37, 34, 44, 9, 57, 37, 19, 13
43+
};
44+
45+
/**
46+
* Default constructor.
47+
*/
48+
public YerushalmiYomiCalculator() {
49+
// No-op
50+
}
51+
52+
/**
53+
* Returns the Daf Yomi Yerushalmi page for a given Jewish date.
54+
* Returns null on Yom Kippur or Tisha B’Av.
55+
* @param jewishCalendar the <code>JewishCalendar</code> to set.
56+
* @return the daf.
57+
*/
58+
public static Daf getDafYomiYerushalmi(JewishCalendar jewishCalendar) {
59+
ZonedDateTime requested = jewishCalendar.getGregorianCalendar().toInstant()
60+
.atZone(ZoneId.systemDefault());
61+
int masechta = 0;
62+
Daf dafYomi = null;
63+
64+
// No Daf Yomi on Yom Kippur or Tisha B'Av
65+
if (jewishCalendar.getYomTovIndex() == JewishCalendar.YOM_KIPPUR ||
66+
jewishCalendar.getYomTovIndex() == JewishCalendar.TISHA_BEAV) {
67+
return null;
68+
}
69+
70+
if (requested.isBefore(DAF_YOMI_START_DAY)) {
71+
throw new IllegalArgumentException(requested + " is prior to the first Daf Yomi cycle starting on "
72+
+ DAF_YOMI_START_DAY);
73+
}
74+
75+
// Initialize cycle dates
76+
ZonedDateTime nextCycle = DAF_YOMI_START_DAY;
77+
ZonedDateTime prevCycle = DAF_YOMI_START_DAY;
78+
79+
// Loop through cycles until we reach the requested date
80+
while (requested.isAfter(nextCycle)) {
81+
prevCycle = nextCycle;
82+
83+
// Add whole cycle days
84+
nextCycle = nextCycle.plusDays(WHOLE_SHAS_DAFS);
85+
nextCycle = nextCycle.plusDays(getNumOfSpecialDays(prevCycle, nextCycle));
86+
}
87+
88+
// Days between start of cycle and requested date
89+
int dafNo = (int) getDiffBetweenDays(prevCycle, requested);
90+
91+
int specialDays = getNumOfSpecialDays(prevCycle, requested);
92+
int total = dafNo - specialDays;
93+
94+
// Find the daf
95+
for (int blatt : BLATT_PER_MASECHTA) {
96+
if (total < blatt) {
97+
dafYomi = new Daf(masechta, total + 1);
98+
break;
99+
}
100+
total -= blatt;
101+
masechta++;
102+
}
103+
104+
return dafYomi;
105+
}
106+
107+
/**
108+
* Counts the number of "special days" (Yom Kippur, Tisha B’Av) between two ZonedDateTimes.
109+
* @param start the start date for the calculation
110+
* @param end the start date for the calculatio
111+
* @return the number of special days
112+
*/
113+
private static int getNumOfSpecialDays(ZonedDateTime start, ZonedDateTime end) {
114+
115+
int startYear = new JewishCalendar(start).getJewishYear();
116+
int endYear = new JewishCalendar(end).getJewishYear();
117+
118+
int specialDays = 0;
119+
120+
// Loop over each Jewish year in range
121+
for (int year = startYear; year <= endYear; year++) {
122+
// Create Yom Kippur and Tisha B’Av for that Jewish year
123+
JewishCalendar yomKippur = new JewishCalendar(5770, 7, 10); // month/day are constants
124+
JewishCalendar tishaBeav = new JewishCalendar(5770, 5, 9);
125+
126+
yomKippur.setJewishYear(year);
127+
tishaBeav.setJewishYear(year);
128+
129+
ZonedDateTime ykDate = yomKippur.getGregorianCalendar().toInstant()
130+
.atZone(start.getZone());
131+
ZonedDateTime tbDate = tishaBeav.getGregorianCalendar().toInstant()
132+
.atZone(start.getZone());
133+
134+
if (isBetween(start, ykDate, end)) specialDays++;
135+
if (isBetween(start, tbDate, end)) specialDays++;
136+
}
137+
138+
return specialDays;
139+
}
140+
141+
/**
142+
* Checks if a date is strictly between start and end.
143+
* @param start the start <code>ZonedDateTime</code>
144+
* @param date the <code>ZonedDateTime</code> to check
145+
* @param end the end <code>ZonedDateTime</code>
146+
* @return if the date is between the two dates
147+
*/
148+
private static boolean isBetween(ZonedDateTime start, ZonedDateTime date, ZonedDateTime end) {
149+
return start.isBefore(date) && end.isAfter(date);
150+
}
151+
152+
/**
153+
* Returns the number of full days between two <code>ZonedDateTime</code>s.
154+
* @param start the start <code>ZonedDateTime</code>
155+
* @param end the end <code>ZonedDateTime</code>
156+
* @return the number of days between the dates.
157+
*/
158+
private static long getDiffBetweenDays(ZonedDateTime start, ZonedDateTime end) {
159+
return (end.toInstant().toEpochMilli() - start.toInstant().toEpochMilli()) / DAY_MILLIS;
160+
}
175161
}

0 commit comments

Comments
 (0)