UNPKG

7.28 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.JewishCalendar = JewishCalendar;
7exports.MoslemToJD = MoslemToJD;
8exports.MoslemLeapYear = MoslemLeapYear;
9exports.JulianToMoslem = JulianToMoslem;
10exports.moslemMonth = moslemMonth;
11
12var _base = require('./base');
13
14var _base2 = _interopRequireDefault(_base);
15
16var _julian = require('./julian');
17
18var _julian2 = _interopRequireDefault(_julian);
19
20function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
22/**
23 * @copyright 2013 Sonia Keys
24 * @copyright 2016 commenthol
25 * @license MIT
26 * @module jm
27 */
28/**
29 * JM: Chapter 9, Jewish and Moslem Calendars.
30 *
31 * The Jewish calendar routines are implemented as a monolithic function,
32 * because computations of the various results build off of common
33 * intermediate results.
34 *
35 * The Moslem calendar routines break down nicely into some separate functions.
36 *
37 * Included in these are two functions that convert between Gregorian and
38 * Julian calendar days without going through Julian day (JD). As such,
39 * I suppose, these or similar routines are not in chapter 7, Julian Day.
40 * Package base might also be a suitable place for these, but I'm not sure
41 * they are used anywhere else in the book. Anyway, they have the quirk
42 * that they are not direct inverses: JulianToGregorian returns the day number
43 * of the day of the Gregorian year, but GregorianToJulian wants the Gregorian
44 * month and day of month as input.
45 */
46
47var int = Math.trunc;
48
49/**
50 * JewishCalendar returns interesting dates and facts about a given year.
51 *
52 * Input is a Julian or Gregorian year.
53 *
54 * Outputs:
55 * A: (int) Year number in the Jewish Calendar
56 * mP: (int) Month number of Pesach.
57 * dP: (int) Day number of Pesach.
58 * mNY: (int) Month number of the Jewish new year.
59 * dNY: (int) Day number of the Jewish new year.
60 * months: (int) Number of months in this year.
61 * days: (int) Number of days in this year.
62 */
63function JewishCalendar(y) {
64 var A = y + 3760;
65 var D = bigD(y);
66 var mP = 3;
67 var dP = D;
68 if (dP > 31) {
69 mP++;
70 dP -= 31;
71 }
72 // A simplification of Meeus's rule to add 163 days. Months of Pesach
73 // are either March or April with D based off of March. Months of New
74 // year are either September or August so D+163-(days from March to
75 // September == 184) = D-21 must be based off of September.
76 var mNY = 9;
77 var dNY = D - 21;
78 if (dNY > 30) {
79 mNY++;
80 dNY -= 30;
81 }
82 var months = 12;
83 switch (A % 19) {
84 case 0:
85 case 3:
86 case 6:
87 case 8:
88 case 11:
89 case 14:
90 case 17:
91 months++;
92 break;
93 }
94 // Similarly, A simplification of Meeus's rule to take the difference
95 // in calendar days from NY of one year to NY of the next. NY is based
96 // on D, so difference in D is difference in day numbers of year. Result
97 // is sum of this number and the number of days in the Western calandar
98 // year.
99 var y1 = y + 1;
100 var lf = _julian2.default.LeapYearGregorian;
101 if (y1 < 1583) {
102 lf = _julian2.default.LeapYearJulian;
103 }
104 var days = 365;
105 if (lf(y1)) {
106 days++;
107 }
108 days += bigD(y1) - D;
109 return [A, mP, dP, mNY, dNY, months, days];
110}
111
112var bigD = function bigD(y) {
113 // (y int) int
114 var C = _base2.default.floorDiv(y, 100);
115 // const S int
116 var S = 0;
117 if (y >= 1583) {
118 S = int(_base2.default.floorDiv(3 * C - 5, 4));
119 }
120 var a = (12 * y + 12) % 19;
121 var b = y % 4;
122 var Q = -1.904412361576 + 1.554241796621 * a + 0.25 * b - 0.003177794022 * y + S;
123 var fq = Math.floor(Q);
124 var iq = int(fq);
125 var j = (iq + 3 * y + 5 * b + 2 - S) % 7;
126 var r = Q - fq;
127 // const D int
128 var D = void 0;
129 if (j === 2 || j === 4 || j === 6) {
130 D = iq + 23;
131 } else if (j === 1 && a > 6 && r >= 0.63287037) {
132 D = iq + 24;
133 } else if (j === 0 && a > 11 && r >= 0.897723765) {
134 D = iq + 23;
135 } else {
136 D = iq + 22;
137 }
138 return int(D);
139};
140
141/**
142 * MoslemToJD converts a Moslem calendar date to a Julian Day.
143 * @param {Number} y - year in moslem calendar
144 * @param {Number} m - month
145 * @param {Number} d - day
146 * @returns {Number} jd - Julian day
147 */
148function MoslemToJD(y, m, d) {
149 // (y, m, d int) (jY, jDN int)
150 var N = d + _base2.default.floorDiv(295001 * (m - 1) + 9900, 10000);
151 var Q = _base2.default.floorDiv(y, 30);
152 var R = y % 30;
153 var A = _base2.default.floorDiv(11 * R + 3, 30);
154 var W = 404 * Q + 354 * R + 208 + A;
155 var Q1 = _base2.default.floorDiv(W, 1461);
156 var Q2 = W % 1461;
157 var G = 621 + 28 * Q + 4 * Q1;
158 var K = _base2.default.floorDiv(Q2 * 10000, 3652422);
159 var E = _base2.default.floorDiv(3652422 * K, 10000);
160 var J = Q2 - E + N - 1;
161 var X = G + K;
162 if (J > 366 && X % 4 === 0) {
163 J -= 366;
164 X++;
165 } else if (J > 365 && X % 4 > 0) {
166 J -= 365;
167 X++;
168 }
169 var jd = _base2.default.floorDiv(36525 * (X - 1), 100) + 1721423 + J;
170 return jd;
171}
172
173/**
174 * MoslemLeapYear returns true if year y of the Moslem calendar is a leap year.
175 * @param {Number} year
176 * @returns {Boolean} true if leap year
177 */
178function MoslemLeapYear(year) {
179 // (y int) bool
180 var R = year % 30;
181 return (11 * R + 3) % 30 > 18;
182}
183
184/**
185 * JulianToMoslem takes a year, month, and day of the Julian calendar and returns the equivalent year, month, and day of the Moslem calendar.
186 *
187 * @param {Number} y - julian year
188 * @param {Number} m - julian month
189 * @param {Number} d - julian day
190 * @returns {Array} [my, mm, md]
191 */
192function JulianToMoslem(y, m, d) {
193 // (y, m, d int) (my, mm, md int)
194 var W = 2;
195 if (y % 4 === 0) {
196 W = 1;
197 }
198 var N = _base2.default.floorDiv(275 * m, 9) - W * _base2.default.floorDiv(m + 9, 12) + d - 30;
199 var A = int(y - 623);
200 var B = _base2.default.floorDiv(A, 4);
201 var C2 = function (A) {
202 var C = A % 4;
203 var C1 = 365.25001 * C;
204 var C2 = Math.floor(C1);
205 if (C1 - C2 > 0.5) {
206 return int(C2) + 1;
207 }
208 return int(C2);
209 }(A);
210 var Dp = 1461 * B + 170 + C2;
211 var Q = _base2.default.floorDiv(Dp, 10631);
212 var R = Dp % 10631;
213 var J = _base2.default.floorDiv(R, 354);
214 var K = R % 354;
215 var O = _base2.default.floorDiv(11 * J + 14, 30);
216 var my = 30 * Q + J + 1;
217 var JJ = K - O + N - 1;
218 var days = 354;
219 if (MoslemLeapYear(y)) {
220 days++;
221 }
222 if (JJ > days) {
223 JJ -= days;
224 my++;
225 }
226 var mm = void 0;
227 var md = void 0;
228 if (JJ === 355) {
229 mm = 12;
230 md = 30;
231 } else {
232 var S = _base2.default.floorDiv((JJ - 1) * 10, 295);
233 mm = 1 + S;
234 md = _base2.default.floorDiv(10 * JJ - 295 * S, 10);
235 }
236 return { year: my, month: mm, day: md };
237}
238
239/**
240 * An MMonth specifies a month of the Moslum Calendar (Muharram = 1, ...).
241 *
242 * Upgraded to Unicode from the spellings given by Meeus.
243 * Source: http://en.wikipedia.org/wiki/Islamic_calendar.
244 */
245var mmonths = ['', 'Muḥarram', 'Ṣafar', 'Rabīʿ I', 'Rabīʿ II', 'Jumādā I', 'Jumādā II', 'Rajab', 'Shaʿbān', 'Ramaḍān', 'Shawwāl', 'Dhū al-Qaʿda', 'Dhū al-Ḥijja'];
246
247/**
248 * String returns the Romanization of the month ("Muḥarram", "Ṣafar", ...).
249 */
250function moslemMonth(m) {
251 return mmonths[m];
252}
253
254exports.default = {
255 JewishCalendar: JewishCalendar,
256 MoslemToJD: MoslemToJD,
257 MoslemLeapYear: MoslemLeapYear,
258 JulianToMoslem: JulianToMoslem,
259 moslemMonth: moslemMonth
260};
\No newline at end of file