UNPKG

hebcal-fixed

Version:

An easy to use, richly-featured, perpetual Jewish Calendar API

327 lines (270 loc) 11.9 kB
/* Hebcal - A Jewish Calendar Generator Copyright (C) 1994-2004 Danny Sadinoff Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved. https://github.com/hebcal/hebcal-js This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Danny Sadinoff can be reached at danny@sadinoff.com Michael Radwin has made significant contributions as a result of maintaining hebcal.com. The JavaScript code was completely rewritten in 2014 by Eyal Schachter. */ /* * Many of the following algorithms were taken from hebrew calendar * routines by Maimonedes, from his Mishneh Torah, and implemented by * Nachum Dershowitz Department of Computer Science * (217) 333-4219 University of Illinois at Urbana-Champaign * nachum@cs.uiuc.edu 1304 West Springfield Avenue * Urbana, Illinois 61801 * * The routines were included in the emacs 19 distribution. * */ var c = require('./common'), HDate = require('./hdate'); var concat = 'concat', range = c.range; // for client optimization var INCOMPLETE = 0, REGULAR = 1, COMPLETE = 2; function Sedra(hebYr, il) { // the Hebrew year il = !!il; var long_c = c.lngChesh(hebYr); var short_k = c.shrtKis(hebYr); var type; this.year = hebYr; if (long_c && !short_k) { type = COMPLETE; } else if (!long_c && short_k) { type = INCOMPLETE; } else { type = REGULAR; } var rosh_hashana = new HDate(1, c.months.TISHREI, hebYr).abs(); var rosh_hashana_day = (rosh_hashana % 7) + 1; // find the first Saturday on or after Rosh Hashana this.first_saturday = c.dayOnOrBefore(6, rosh_hashana + 6); var leap = +c.LEAP(hebYr); this.type = type; this.rosh_hashana_day = rosh_hashana_day; this.leap = leap; this.il = il; var core = "" + leap + rosh_hashana_day + type; if (types[core]) { this.theSedraArray = types[core]; } else { this.theSedraArray = types[core + (+il)]; // cast to num, then concat } if (!this.theSedraArray) { console.log(this); throw new TypeError("improper sedra year type calculated."); } } var parshiot = Sedra.parshiot = [ [ 'Bereshit', 'Bereshis', 'בראשית' ], // 0 [ 'Noach', 0, 'נח' ], [ 'Lech-Lecha', 0, 'לך-לך' ], [ 'Vayera', 0, 'וירא' ], [ 'Chayei Sara', 0, 'חי שרה' ], [ 'Toldot', 'Toldos', 'תולדות' ], [ 'Vayetzei', 0, 'ויצא' ], [ 'Vayishlach', 0, 'וישלח' ], [ 'Vayeshev', 0, 'וישב' ], [ 'Miketz', 0, 'מקץ' ], [ 'Vayigash', 0, 'ויגש' ], // 10 [ 'Vayechi', 0, 'ויחי' ], [ 'Shemot', 'Shemos', 'שמות' ], [ 'Vaera', 0, 'וארא' ], [ 'Bo', 0, 'בא' ], [ 'Beshalach', 0, 'בשלח' ], [ 'Yitro', 'Yisro', 'יתרו' ], [ 'Mishpatim', 0, 'משפטים' ], [ 'Terumah', 0, 'תרומה' ], [ 'Tetzaveh', 0, 'תצוה' ], [ 'Ki Tisa', 'Ki Sisa', 'כי תשא' ], // 20 [ 'Vayakhel', 0, 'ויקהל' ], [ 'Pekudei', 0, 'פקודי' ], [ 'Vayikra', 0, 'ויקרא' ], [ 'Tzav', 0, 'צו' ], [ 'Shmini', 0, 'שמיני' ], [ 'Tazria', 0, 'תזריע' ], [ 'Metzora', 0, 'מצרע' ], [ 'Achrei Mot', 'Achrei Mos', 'אחרי מות' ], [ 'Kedoshim', 0, 'קדשים' ], [ 'Emor', 0, 'אמור' ], // 30 [ 'Behar', 0, 'בהר' ], [ 'Bechukotai', 'Bechukosai', 'בחקתי' ], [ 'Bamidbar', 0, 'במדבר' ], [ 'Nasso', 0, 'נשא' ], [ 'Beha\'alotcha', 'Beha\'aloscha', 'בהעלתך' ], [ 'Sh\'lach', 0, 'שלח לך' ], [ 'Korach', 0, 'קורח' ], [ 'Chukat', 'Chukas', 'חקת' ], [ 'Balak', 0, 'בלק' ], [ 'Pinchas', 0, 'פינחס' ], // 40 [ 'Matot', 'Matos', 'מטות' ], [ 'Masei', 0, 'מסעי' ], [ 'Devarim', 0, 'דברים' ], [ 'Vaetchanan', 'V\'eschanan', 'ואתחנן' ], [ 'Eikev', 0, 'עקב' ], [ 'Re\'eh', 0, 'ראה' ], [ 'Shoftim', 0, 'שופטים' ], [ 'Ki Teitzei', 'Ki Seitzei', 'כי תצא' ], [ 'Ki Tavo', 'Ki Savo', 'כי תבוא' ], [ 'Nitzavim', 0, 'נצבים' ], // 50 [ 'Vayeilech', 0, 'וילך' ], [ 'Ha\'Azinu', 0, 'האזינו' ] ]; // parsha doubler/undoubler function D(p) { return -p; } // these are wrapped to protect them from [].concat() var RH = [[ 'Rosh Hashana', 0, 'ראש השנה' ]]; //0 var YK = [[ 'Yom Kippur', 0, 'יום כיפור' ]]; //1 var SUKKOT = [[ 'Sukkot', 'Succos', 'סוכות' ]]; //0 var CHMSUKOT = [[ 'Chol hamoed Sukkot', 'Chol hamoed Succos', 'חול המועד סוכות' ]]; //0 var SHMINI = [[ 'Shmini Atzeret', 'Shmini Atzeres', 'שמיני עצרת' ]]; //0 var EOY = [[ 'End-of-Year: Simchat-Torah, Sukkot', 'End-of-Year: Simchas-Torah, Succos', 'סופשנה: סוכות וסמחת תורה' ]]; //0 var PESACH = [[ 'Pesach', 0, 'פסח' ]]; //25 var CHMPESACH = [[ 'Chol hamoed Pesach', 0, 'חול המועד פסח' ]]; //25 var PESACH7 = [[ 'Second days of Pesach', 0, 'שביעי של פסח' ]]; //25 var SHAVUOT = [[ 'Shavuot', 'Shavuos', 'שבועות' ]]; //33 // The ordinary year types (keviot) // names are leap/nonleap - day - incomplete/regular/complete - diaspora/Israel var types = { /* Hebrew year that starts on Monday, is `incomplete' (Heshvan and * Kislev each have 29 days), and has Passover start on Tuesday. */ //e.g. 5753 '020' : [51, 52][concat](EOY, range(0, 20), D(21), 23, 24, PESACH, 25, D(26), D(28), 30, D(31), range(33, 40), D(41), range(43, 49), D(50) ), /* Hebrew year that starts on Monday, is `complete' (Heshvan and * Kislev each have 30 days), and has Passover start on Thursday. */ //e.g. 5756 '0220' : [51, 52][concat](EOY, range(0, 20), D(21), 23, 24, PESACH, 25, D(26), D(28), 30, D(31), 33, SHAVUOT, range(34, 37), D(38), 40, D(41), range(43, 49), D(50) ), /* Hebrew year that starts on Thursday, is `regular' (Heshvan has 29 * days and Kislev has 30 days), and has Passover start on Saturday. */ //e.g. 5701 '0510' : [52][concat](YK, EOY, range(0, 20), D(21), 23, 24, PESACH, PESACH, 25, D(26), D(28), 30, D(31), range(33, 40), D(41), range(43, 50) ), /* Hebrew year that starts on Thursday, is `regular' (Heshvan has 29 * days and Kislev has 30 days), and has Passover start on Saturday. */ // e.g. 5745 '0511' : [52][concat](YK, EOY, range(0, 20), D(21), 23, 24, PESACH, 25, D(26), D(28), range(30, 40), D(41), range(43, 50) ), /* Hebrew year that starts on Thursday, is `complete' (Heshvan and * Kislev each have 30 days), and has Passover start on Sunday. */ //e.g. 5754 '052' : [52][concat](YK, CHMSUKOT, range(0, 24), PESACH7, 25, D(26), D(28), 30, D(31), range(33, 40), D(41), range(43, 50) ), /* Hebrew year that starts on Saturday, is `incomplete' (Heshvan and Kislev * each have 29 days), and has Passover start on Sunday. */ //e.g. 5761 '070' : [][concat](RH, 52, SUKKOT, SHMINI, range(0, 20), D(21), 23, 24, PESACH7, 25, D(26), D(28), 30, D(31), range(33, 40), D(41), range(43, 50) ), /* Hebrew year that starts on Saturday, is `complete' (Heshvan and * Kislev each have 30 days), and has Passover start on Tuesday. */ //e.g. 5716 '072' : [][concat](RH, 52, SUKKOT, SHMINI, range(0, 20), D(21), 23, 24, CHMPESACH, 25, D(26), D(28), 30, D(31), range(33, 40), D(41), range(43, 49), D(50) ), /* -- The leap year types (keviot) -- */ /* Hebrew year that starts on Monday, is `incomplete' (Heshvan and * Kislev each have 29 days), and has Passover start on Thursday. */ //e.g. 5746 '1200' : [51, 52][concat](CHMSUKOT, range(0, 27), CHMPESACH, range(28, 33), SHAVUOT, range(34, 37), D(38), 40, D(41), range(43, 49), D(50) ), /* Hebrew year that starts on Monday, is `incomplete' (Heshvan and * Kislev each have 29 days), and has Passover start on Thursday. */ //e.g. 5746 '1201' : [51, 52][concat](CHMSUKOT, range(0, 27), CHMPESACH, range(28, 40), D(41), range(43, 49), D(50) ), /* Hebrew year that starts on Monday, is `complete' (Heshvan and * Kislev each have 30 days), and has Passover start on Saturday. */ //e.g.5752 '1220' : [51, 52][concat](CHMSUKOT, range(0, 27), PESACH, PESACH, range(28, 40), D(41), range(43, 50) ), /* Hebrew year that starts on Monday, is `complete' (Heshvan and * Kislev each have 30 days), and has Passover start on Saturday. */ //e.g.5752 '1221' : [51, 52][concat](CHMSUKOT, range(0, 27), PESACH, range(28, 50)), /* Hebrew year that starts on Thursday, is `incomplete' (Heshvan and * Kislev both have 29 days), and has Passover start on Sunday. */ //e.g. 5768 '150' : [52][concat](YK, CHMSUKOT, range(0, 28), PESACH7, range(29, 50)), /* Hebrew year that starts on Thursday, is `complete' (Heshvan and * Kislev both have 30 days), and has Passover start on Tuesday. */ //eg. 5771 '152' : [52][concat](YK, CHMSUKOT, range(0, 28), CHMPESACH, range(29, 49), D(50)), /* Hebrew year that starts on Saturday, is `incomplete' (Heshvan and * Kislev each have 29 days), and has Passover start on Tuesday. */ //e.g.5757 '170' : [][concat](RH, 52, SUKKOT, SHMINI, range(0, 27), CHMPESACH, range(28, 40), D(41), range(43, 49), D(50) ), /* Hebrew year that starts on Saturday, is `complete' (Heshvan and * Kislev each have 30 days), and has Passover start on Thursday. */ '1720' : [][concat](RH, 52, SUKKOT, SHMINI, range(0, 27), CHMPESACH, range(28, 33), SHAVUOT, range(34, 37), D(38), 40, D(41), range(43, 49), D(50) ) }; /* Hebrew year that starts on Monday, is `complete' (Heshvan and * Kislev each have 30 days), and has Passover start on Thursday. */ types['0221'] = types['020']; /* Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 * days and Kislev has 30 days), and has Passover start on Thursday. */ //e.g. 5715 types['0310'] = types['0220']; /* Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 * days and Kislev has 30 days), and has Passover start on Thursday. */ types['0311'] = types['020']; /* Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 * days and Kislev has 30 days), and has Passover start on Saturday. */ // e.g. 5715 types['1310'] = types['1220']; /* Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 * days and Kislev has 30 days), and has Passover start on Saturday. */ types['1311'] = types['1221']; /* Hebrew year that starts on Saturday, is `complete' (Heshvan and * Kislev each have 30 days), and has Passover start on Thursday. */ types['1721'] = types['170']; Sedra.prototype.get = function(hDate) { return abs(this, hDate.abs()); }; // returns an array describing the parsha on the first Saturday on or after absdate function abs(year, absDate) { // find the first saturday on or after today's date absDate = c.dayOnOrBefore(6, absDate + 6); var weekNum = (absDate - year.first_saturday) / 7; var index = year.theSedraArray[weekNum]; if (undefined === index) { return abs(new Sedra(year.year + 1, year.il), absDate); // must be next year } if (typeof index == 'object') { // Shabbat has a chag. Return a description return [index]; } if (index >= 0) { return [parshiot[index]]; } index = D(index); // undouble the parsha return [parshiot[index], parshiot[index + 1]]; } module.exports = Sedra;