001/* 002 * Zmanim Java API 003 * Copyright (C) 2011-2025 Eliyahu Hershfeld 004 * 005 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General 006 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) 007 * any later version. 008 * 009 * This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied 010 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 011 * details. 012 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to 013 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA, 014 * or connect to: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html 015 */ 016package com.kosherjava.zmanim.hebrewcalendar; 017 018import java.util.Calendar; 019import java.util.GregorianCalendar; 020 021/** 022 * This class calculates the Daf Yomi Bavli page (daf) for a given date. To calculate Daf Yomi Yerushalmi 023 * use the {@link YerushalmiYomiCalculator}. The library may cover Mishna Yomi etc. at some point in the future. 024 * 025 * @author © Bob Newell (original C code) 026 * @author © Eliyahu Hershfeld 2011 - 2025 027 */ 028public class YomiCalculator { 029 030 /** 031 * The start date of the first Daf Yomi Bavli cycle of September 11, 1923 / Rosh Hashana 5684. 032 */ 033 private static final Calendar dafYomiStartDay = new GregorianCalendar(1923, Calendar.SEPTEMBER, 11); 034 /** The start date of the first Daf Yomi Bavli cycle in the Julian calendar. Used internally for calculations.*/ 035 private static final int dafYomiJulianStartDay = getJulianDay(dafYomiStartDay); 036 /** 037 * The date that the pagination for the Daf Yomi <em>Maseches Shekalim</em> changed to use the commonly used Vilna 038 * Shas pagination from the no longer commonly available Zhitomir / Slavuta Shas used by Rabbi Meir Shapiro. 039 */ 040 private static final Calendar shekalimChangeDay = new GregorianCalendar(1975, Calendar.JUNE, 24); 041 042 /** The Julian date that the cycle for Shekalim changed. 043 * @see #getDafYomiBavli(JewishCalendar) for details. 044 */ 045 private static final int shekalimJulianChangeDay = getJulianDay(shekalimChangeDay); 046 047 /** 048 * Default constructor. 049 */ 050 public YomiCalculator() { 051 // nothing here 052 } 053 054 /** 055 * Returns the <a href="http://en.wikipedia.org/wiki/Daf_yomi">Daf Yomi</a> <a 056 * href="http://en.wikipedia.org/wiki/Talmud">Bavli</a> {@link Daf} for a given date. The first Daf Yomi cycle 057 * started on Rosh Hashana 5684 (September 11, 1923) and calculations prior to this date will result in an 058 * IllegalArgumentException thrown. For historical calculations (supported by this method), it is important to note 059 * that a change in length of the cycle was instituted starting in the eighth Daf Yomi cycle beginning on June 24, 060 * 1975. The Daf Yomi Bavli cycle has a single masechta of the Talmud Yerushalmi - Shekalim as part of the cycle. 061 * Unlike the Bavli where the number of daf per masechta was standardized since the original <a 062 * href="http://en.wikipedia.org/wiki/Daniel_Bomberg">Bomberg Edition</a> published from 1520 - 1523, there is no 063 * uniform page length in the Yerushalmi. The early cycles had the Yerushalmi Shekalim length of 13 days following the 064 * <a href= 065 * "https://he.wikipedia.org/wiki/%D7%93%D7%A4%D7%95%D7%A1_%D7%A1%D7%9C%D7%90%D7%95%D7%95%D7%99%D7%98%D7%90">Slavuta/Zhytomyr</a> 066 * Shas used by <a href="http://en.wikipedia.org/wiki/Meir_Shapiro">Rabbi Meir Shapiro</a>. With the start of the eighth Daf Yomi 067 * cycle beginning on June 24, 1975, the length of the Yerushalmi Shekalim was changed from 13 to 22 daf to follow 068 * the <a href="https://en.wikipedia.org/wiki/Vilna_Edition_Shas">Vilna Shas</a> that is in common use today. 069 * 070 * @param jewishCalendar 071 * The JewishCalendar date for calculation. TODO: this can be changed to use a regular GregorianCalendar since 072 * there is nothing specific to the JewishCalendar in this class. 073 * @return the {@link Daf}. 074 * 075 * @throws IllegalArgumentException 076 * if the date is prior to the September 11, 1923, the start date of the first Daf Yomi cycle. 077 */ 078 public static Daf getDafYomiBavli(JewishCalendar jewishCalendar) { 079 /* 080 * The number of daf per masechta. Since the number of blatt in Shekalim changed on the 8th Daf Yomi cycle 081 * beginning on June 24, 1975, from 13 to 22, the actual calculation for blattPerMasechta[4] will later be 082 * adjusted based on the cycle. 083 */ 084 int[] blattPerMasechta = { 64, 157, 105, 121, 22, 88, 56, 40, 35, 31, 32, 29, 27, 122, 112, 91, 66, 49, 90, 82, 085 119, 119, 176, 113, 24, 49, 76, 14, 120, 110, 142, 61, 34, 34, 28, 22, 4, 9, 5, 73 }; 086 Calendar calendar = jewishCalendar.getGregorianCalendar(); 087 088 Daf dafYomi = null; 089 int julianDay = getJulianDay(calendar); 090 int cycleNo; 091 int dafNo; 092 if (calendar.before(dafYomiStartDay)) { 093 // TODO: should we return a null or throw an IllegalArgumentException? 094 throw new IllegalArgumentException(calendar + " is prior to organized Daf Yomi Bavli cycles that started on " 095 + dafYomiStartDay); 096 } 097 if (calendar.equals(shekalimChangeDay) || calendar.after(shekalimChangeDay)) { 098 cycleNo = 8 + ((julianDay - shekalimJulianChangeDay) / 2711); 099 dafNo = ((julianDay - shekalimJulianChangeDay) % 2711); 100 } else { 101 cycleNo = 1 + ((julianDay - dafYomiJulianStartDay) / 2702); 102 dafNo = ((julianDay - dafYomiJulianStartDay) % 2702); 103 } 104 105 int total = 0; 106 int masechta = -1; 107 int blatt; 108 109 // Fix Shekalim for old cycles. 110 if (cycleNo <= 7) { 111 blattPerMasechta[4] = 13; 112 } 113 114 // Finally find the daf. 115 for (int i : blattPerMasechta) { 116 masechta++; 117 total = total + i - 1; 118 if (dafNo < total) { 119 blatt = 1 + i - (total - dafNo); 120 // Fiddle with the weird ones near the end. 121 if (masechta == 36) { 122 blatt += 21; 123 } else if (masechta == 37) { 124 blatt += 24; 125 } else if (masechta == 38) { 126 blatt += 32; 127 } 128 dafYomi = new Daf(masechta, blatt); 129 break; 130 } 131 } 132 133 return dafYomi; 134 } 135 136 /** 137 * Return the <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> from a Java Calendar. 138 * 139 * @param calendar 140 * The Java Calendar of the date to be calculated 141 * @return the Julian day number corresponding to the date 142 */ 143 private static int getJulianDay(Calendar calendar) { 144 int year = calendar.get(Calendar.YEAR); 145 int month = calendar.get(Calendar.MONTH) + 1; 146 int day = calendar.get(Calendar.DAY_OF_MONTH); 147 if (month <= 2) { 148 year -= 1; 149 month += 12; 150 } 151 int a = year / 100; 152 int b = 2 - a + a / 4; 153 return (int) (Math.floor(365.25 * (year + 4716)) + Math.floor(30.6001 * (month + 1)) + day + b - 1524.5); 154 } 155}