@@ -11,12 +11,13 @@ import masoretic from './masoretic.json.js';
11
11
const startDate = new Date ( 1948 , 9 , 26 ) ;
12
12
export const tanakhYomiStart = greg . greg2abs ( startDate ) ;
13
13
14
+ const JOSHUA = 'Joshua' ;
14
15
const JEREMIAH = 'Jeremiah' ;
15
16
const RUTH = 'Ruth' ;
16
17
const SHIR_HASHIRIM = 'Song of Songs' ;
17
18
18
19
const books = [
19
- [ 'Joshua' , 14 ] ,
20
+ [ JOSHUA , 14 ] ,
20
21
[ 'Judges' , 14 ] ,
21
22
[ 'Samuel' , 34 ] ,
22
23
[ 'Kings' , 35 ] ,
@@ -63,51 +64,48 @@ export function tanakhYomi(date) {
63
64
const hyear = hd . getFullYear ( ) ;
64
65
const rh = HDate . hebrew2abs ( hyear , months . TISHREI , 1 ) ;
65
66
const startAbs = rh + 22 ;
66
- const table = books . slice ( ) ;
67
- const longCheshvan = HDate . longCheshvan ( hyear ) ;
68
- let longRuth = false ;
69
- if ( HDate . isLeapYear ( hyear ) || longCheshvan ) {
70
- table [ 12 ] = { name : RUTH , blatt : 2 } ; // Ruth gets 2 days
71
- longRuth = true ;
72
- }
73
- let longShirHaShirim = false ;
74
- if ( longCheshvan ) {
75
- table [ 11 ] = { name : SHIR_HASHIRIM , blatt : 2 } ; // Shir HaShirim gets 2 days
76
- longShirHaShirim = true ;
77
- }
78
- let longJeremiah = false ;
79
- if ( longCheshvan && ! HDate . shortKislev ( hyear ) ) {
80
- table [ 5 ] = { name : JEREMIAH , blatt : 32 } ; // Jeremiah 9 gets split across two days
81
- longJeremiah = true ;
82
- }
83
-
84
67
if ( cday < startAbs ) {
85
- let blatt = rh % 7 === 6 ? 10 : 12 ;
68
+ const rhDow = rh % 7 ;
69
+ let blatt = rhDow === 4 ? 11 : rhDow === 6 ? 10 : 12 ;
86
70
for ( let i = rh + 2 ; i < cday ; i ++ ) {
87
71
const hdate = new HDate ( i ) ;
88
72
if ( ! skipDay ( hdate ) ) {
89
73
blatt ++ ;
90
74
}
91
75
}
76
+ if ( blatt === 26 ) {
77
+ throw new Error ( `${ hd . toString ( ) } Chronicles ${ blatt } ` ) ;
78
+ }
92
79
return new TanakhYomi ( 'Chronicles' , blatt ) ;
93
80
}
94
-
95
81
let total = 0 ;
96
82
for ( let i = startAbs ; i < cday ; i ++ ) {
97
83
const hdate = new HDate ( i ) ;
98
84
if ( ! skipDay ( hdate ) ) {
99
85
total ++ ;
100
86
}
101
87
}
88
+ const readingTable = makeReadingTable ( hyear ) ;
89
+ const table = readingTable . table ;
90
+
102
91
for ( let j = 0 ; j < table . length ; j ++ ) {
103
92
if ( total < table [ j ] . blatt ) {
104
93
const blatt = total + 1 ;
105
94
const name = table [ j ] . name ;
106
- if ( ( longShirHaShirim && name === SHIR_HASHIRIM ) ||
107
- ( longRuth && name === RUTH ) ) {
95
+ if ( ( readingTable . longShirHaShirim && name === SHIR_HASHIRIM ) ||
96
+ ( readingTable . longRuth && name === RUTH ) ) {
108
97
return new TanakhYomi ( name , '1.' + blatt ) ;
109
98
}
110
- if ( longJeremiah && name === JEREMIAH && blatt >= 9 ) {
99
+ if ( readingTable . longJoshua && name === JOSHUA && blatt >= 4 ) {
100
+ if ( blatt === 4 ) {
101
+ return new TanakhYomi ( name , '4.1' ) ;
102
+ } else if ( blatt === 5 ) {
103
+ return new TanakhYomi ( name , '4.2' ) ;
104
+ } else {
105
+ return new TanakhYomi ( name , blatt - 1 ) ;
106
+ }
107
+ }
108
+ if ( readingTable . longJeremiah && name === JEREMIAH && blatt >= 9 ) {
111
109
if ( blatt === 9 ) {
112
110
return new TanakhYomi ( name , '9.1' ) ;
113
111
} else if ( blatt === 10 ) {
@@ -146,11 +144,84 @@ function skipDay(hd) {
146
144
return false ;
147
145
}
148
146
149
- const splitSeder = {
150
- 'Jeremiah' : { '9.1' : '17:7-25' , '9.2' : '17:26-18:18' } ,
151
- 'Song of Songs' : { '1.1' : '1:1-5:1' , '1.2' : '5:2-8:14' } ,
152
- 'Ruth' : { '1.1' : '1:1-2:11' , '1.2' : '2:12-4:22' } ,
153
- } ;
147
+ /**
148
+ * @private
149
+ * @param {number } year
150
+ * @return {number }
151
+ */
152
+ function calculateNumDaysToRead ( year ) {
153
+ const startAbs = HDate . hebrew2abs ( year , months . TISHREI , 23 ) ;
154
+ const endAbs = HDate . hebrew2abs ( year + 1 , months . TISHREI , 22 ) ;
155
+ let included = 0 ;
156
+ for ( let abs = startAbs ; abs <= endAbs ; abs ++ ) {
157
+ const hdate = new HDate ( abs ) ;
158
+ if ( ! skipDay ( hdate ) ) {
159
+ included ++ ;
160
+ }
161
+ }
162
+ return included ;
163
+ }
164
+
165
+ /**
166
+ * A common year can have a length of 353, 354 or 355 days
167
+ * A leap year can have a length of 383, 384 or 385 days
168
+ *
169
+ * Common years can have
170
+ * 293 chapters - no extra chapters (45%)
171
+ * 294 chapters - 1 extra chapter (5%)
172
+ * 295 chapters - 2 extra chapters (31%)
173
+ * 296 chapters - 3 extra chapters (19%)
174
+ * Leap years can have
175
+ * 318 chapters - no extra chapters (10%)
176
+ * 319 chapters - 1 extra chapter (30%)
177
+ * 320 chapters - 2 extra chapters (47%)
178
+ * 222 chapters - 4 extra chapters (12%)
179
+ *
180
+ * @private
181
+ * @param {number } year
182
+ * @return {any }
183
+ */
184
+ function makeReadingTable ( year ) {
185
+ const numDays = calculateNumDaysToRead ( year ) ;
186
+ const count = HDate . isLeapYear ( year ) ? numDays - 25 : numDays ;
187
+ const extra = count - 293 ;
188
+ const table = books . slice ( ) ;
189
+ const result = {
190
+ numDays,
191
+ table,
192
+ longRuth : false ,
193
+ longShirHaShirim : false ,
194
+ longJeremiah : false ,
195
+ longJoshua : false ,
196
+ } ;
197
+ switch ( extra ) {
198
+ case 0 :
199
+ return result ;
200
+ case 4 :
201
+ // Joshua 4 gets split across two days
202
+ table [ 0 ] = { name : JOSHUA , blatt : 15 } ;
203
+ result . longJoshua = true ;
204
+ /* FALLTHROUGH */
205
+ case 3 :
206
+ // Jeremiah 9 gets split across two days
207
+ table [ 5 ] = { name : JEREMIAH , blatt : 32 } ;
208
+ result . longJeremiah = true ;
209
+ /* FALLTHROUGH */
210
+ case 2 :
211
+ // Shir HaShirim gets 2 days
212
+ table [ 11 ] = { name : SHIR_HASHIRIM , blatt : 2 } ;
213
+ result . longShirHaShirim = true ;
214
+ /* FALLTHROUGH */
215
+ case 1 :
216
+ // Ruth gets 2 days
217
+ table [ 12 ] = { name : RUTH , blatt : 2 } ;
218
+ result . longRuth = true ;
219
+ break ;
220
+ default :
221
+ throw new Error ( `${ year } => ${ numDays } ${ count } ${ extra } ` ) ;
222
+ }
223
+ return result ;
224
+ }
154
225
155
226
/**
156
227
* Returns the Daf Yomi for given date
@@ -163,9 +234,12 @@ export class TanakhYomi extends DafPage {
163
234
*/
164
235
constructor ( name , blatt ) {
165
236
super ( name , blatt ) ;
166
- const seders = masoretic [ name ] ;
237
+ const seders = masoretic . regular [ name ] ;
167
238
const verses = typeof blatt === 'number' ?
168
- seders [ blatt - 1 ] : splitSeder [ name ] [ blatt ] ;
239
+ seders [ blatt - 1 ] : masoretic . split [ name ] [ blatt ] ;
240
+ if ( ! verses ) {
241
+ throw new Error ( `${ name } ${ blatt } ` ) ;
242
+ }
169
243
const firstChar = verses . charCodeAt ( 0 ) ;
170
244
this . verses = firstChar >= 48 && firstChar <= 57 ?
171
245
`${ name } ${ verses } ` : verses ;
@@ -182,10 +256,17 @@ export class TanakhYomi extends DafPage {
182
256
locale = locale . toLowerCase ( ) ;
183
257
}
184
258
const name = Locale . gettext ( this . name , locale ) ;
259
+ const blatt = this . blatt ;
185
260
if ( locale === 'he' || locale === 'he-x-nonikud' ) {
186
- return name + ' ס׳ ' + gematriya ( this . blatt ) ;
261
+ const prefix = name + ' ס׳ ' ;
262
+ if ( typeof blatt === 'string' ) {
263
+ const major = blatt [ 0 ] ;
264
+ const minor = blatt [ 2 ] ;
265
+ return prefix + gematriya ( + major ) + minor ;
266
+ }
267
+ return prefix + gematriya ( blatt ) ;
187
268
}
188
- return name + ' Seder ' + this . blatt ;
269
+ return name + ' Seder ' + blatt ;
189
270
}
190
271
}
191
272
0 commit comments