1 /*
2 Hebcal - A Jewish Calendar Generator
3 Copyright (C) 1994-2004 Danny Sadinoff
4 Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved.
5
6 https://github.com/hebcal/hebcal
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 Danny Sadinoff can be reached at
23
24 danny@sadinoff.com
25 */
26
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include "common.h"
30 #include "greg.h"
31 #include "hebcal.h"
32
33 hmonths_t hMonths =
34 {
35 {
36 {"VOID"},
37 {"Nisan"},
38 {"Iyyar"},
39 {"Sivan"},
40 {"Tamuz"},
41 {"Av"},
42 {"Elul"},
43 {"Tishrei"},
44 {"Cheshvan"},
45 {"Kislev"},
46 {"Tevet"},
47 {"Sh'vat"},
48 {"Adar"},
49 {"Nisan"}
50 },
51 {
52 {"VOID"},
53 {"Nisan"},
54 {"Iyyar"},
55 {"Sivan"},
56 {"Tamuz"},
57 {"Av"},
58 {"Elul"},
59 {"Tishrei"},
60 {"Cheshvan"},
61 {"Kislev"},
62 {"Tevet"},
63 {"Sh'vat"},
64 {"Adar I"},
65 {"Adar II"},
66 {"Nisan"}
67 }
68 };
69
max_days_in_heb_month(int month,int year)70 int max_days_in_heb_month (int month, int year)
71 {
72 if ( month == IYYAR ||
73 month == TAMUZ ||
74 month == ELUL ||
75 month == TEVET ||
76 month == ADAR_II ||
77 (month == ADAR_I && !LEAP_YR_HEB( year )) ||
78 (month == CHESHVAN && !long_cheshvan( year )) ||
79 (month == KISLEV && short_kislev( year )))
80 return 29;
81 else
82 return 30;
83 }
84
lookup_hebrew_month(const char * s)85 int lookup_hebrew_month( const char *s )
86 {
87 /* the hebrew months are unique to their second letter
88 N nisan (november?)
89 I iyyar
90 E Elul
91 C Cheshvan
92 K Kislev
93 1 1Adar
94 2 2Adar
95 Si Sh sivan, Shvat
96 Ta Ti Te Tamuz, Tishrei, Tevet
97 Av Ad Av, Adar
98 */
99 switch ( tolower( *s++ ))
100 {
101 case 'n':
102 return (tolower (*s) == 'o') ? /* this catches "november" */
103 0
104 : NISAN;
105 case 'i':
106 return IYYAR;
107 case 'e':
108 return ELUL;
109 case 'c':
110 return CHESHVAN;
111 case 'k':
112 return KISLEV;
113 case 's':
114 switch (tolower (*s))
115 {
116 case 'i':
117 return SIVAN;
118 case 'h':
119 return SHVAT;
120 default:
121 return 0;
122 }
123 case 't':
124 switch (tolower (*s))
125 {
126 case 'a':
127 return TAMUZ;
128 case 'i':
129 return TISHREI;
130 case 'e':
131 return TEVET;
132 default:
133 return 0;
134 }
135 case 'a':
136 switch (tolower (*s))
137 {
138 case 'v':
139 return AV;
140 case 'd':
141 for (; *s; s++)
142 { /* scan for a 1. */
143 if (*s == '1')
144 return ADAR_I;
145 }
146 return ADAR_II; /* else assume sheni */
147 default:
148 return 0;
149 }
150 default:
151 return 0;
152 }
153 }
154
155
156
157
158 /*
159 returns day of week, hours and chalakim of specified molad.
160 */
get_molad(int year,int month)161 molad_t get_molad( int year, int month)
162 {
163 molad_t retMolad;
164
165 long yearl, m_elapsed, p_elapsed, h_elapsed, parts, m_adj;
166
167 m_adj = (long) month;
168 m_adj -= 7;
169 if (m_adj < 0) m_adj += MONTHS_IN_HEB(year);
170
171 yearl = (long) year;
172 m_elapsed = m_adj +
173 235L * ((yearl - 1L) / 19L) +
174 12L * ((yearl - 1L) % 19) +
175 ((((yearl - 1L) % 19L) * 7) + 1L) / 19L;
176
177 p_elapsed = 204L + (793L * (m_elapsed % 1080));
178
179 h_elapsed = 5L + (12L * m_elapsed) +
180 793L * (m_elapsed / 1080L) +
181 p_elapsed / 1080L -
182 6L;
183
184 parts = (p_elapsed % 1080) + 1080 * (h_elapsed % 24);
185
186 retMolad.day = 1L + 29L * m_elapsed + h_elapsed / 24L;
187 retMolad.hour = (int) (h_elapsed % 24L);
188 retMolad.chalakim = (int) (parts % 1080L);
189
190 return retMolad;
191
192 }
193
194
abs2hebrew(long d)195 date_t abs2hebrew( long d )
196 {
197 static int mmap[] =
198 {
199 KISLEV, TEVET, SHVAT, ADAR_I, NISAN,
200 IYYAR, SIVAN, TAMUZ,
201 TISHREI, TISHREI, TISHREI, CHESHVAN
202 };
203 date_t hebdate, gregdate;
204 int day, month, year;
205
206 if( d >= 10555144L )
207 {
208 fprintf(stderr, "parameter to abs2hebrew %ld out of range\n",
209 d );
210 exit(1);
211 }
212
213 gregdate = abs2greg (d);
214 hebdate.dd = 1;
215 hebdate.mm = 7;
216 year = 3760 + gregdate.yy;
217
218 while (hebdate.yy = year + 1,
219 d >= hebrew2abs (hebdate))
220 year++;
221
222 if( year >= 4635 && year < 10666 )
223 {
224 /* optimize search */
225 month = mmap[gregdate.mm - 1];
226 }
227 else
228 {
229 /* we're outside the usual range, so assume nothing about hebrew/gregorian calendar drift... */
230 month = TISHREI;
231 }
232
233 while (hebdate.mm = month,
234 hebdate.dd = max_days_in_heb_month (month, year),
235 hebdate.yy = year,
236 d > hebrew2abs (hebdate))
237 month = (month % MONTHS_IN_HEB (year)) + 1;
238
239 hebdate.dd = 1;
240
241 day = (int) (d - hebrew2abs (hebdate) + 1L);
242 if( day < 0)
243 {
244 fprintf(stderr, "assertion failure d < hebrew2abs(m,d,y) => %ld < %ld!\n",
245 d, hebrew2abs(hebdate));
246 exit(1);
247 }
248
249 hebdate.dd = day;
250
251 return hebdate;
252 }
253
254
255 /* Days from sunday prior to start of hebrew calendar to mean
256 conjunction of tishrei in hebrew YEAR
257 */
hebrew_elapsed_days(int year)258 static long int hebrew_elapsed_days (int year)
259 {
260 long int yearl, m_elapsed, p_elapsed, h_elapsed, parts, day, alt_day;
261
262 yearl = (long) year;
263 m_elapsed = 235L * ((yearl - 1L) / 19L) +
264 12L * ((yearl - 1L) % 19L) +
265 ((((yearl - 1L) % 19L) * 7L) + 1L) / 19L;
266
267 p_elapsed = 204L + (793L * (m_elapsed % 1080L));
268
269 h_elapsed = 5L + (12L * m_elapsed) +
270 793L * (m_elapsed / 1080L) +
271 p_elapsed / 1080L;
272
273 parts = (p_elapsed % 1080L) + 1080L * (h_elapsed % 24L);
274
275 day = 1L + 29L * m_elapsed + h_elapsed / 24L;
276
277 if ((parts >= 19440L) ||
278 ((2L == (day % 7L)) && (parts >= 9924L) && !(LEAP_YR_HEB (year))) ||
279 ((1L == (day % 7L)) && (parts >= 16789L) && LEAP_YR_HEB (year - 1)))
280 alt_day = day + 1L;
281 else
282 alt_day = day;
283
284 if ((alt_day % 7L) == 0L ||
285 (alt_day % 7L) == 3L ||
286 (alt_day % 7L) == 5L)
287 return alt_day + 1L;
288 else
289 return alt_day;
290 }
291
292
293
294 /* convert hebrew date to absolute date */
295 /*Absolute date of Hebrew DATE.
296 The absolute date is the number of days elapsed since the (imaginary)
297 Gregorian date Sunday, December 31, 1 BC. */
hebrew2abs(date_t d)298 long hebrew2abs (date_t d)
299 {
300 int m;
301 long tempabs = (long) d.dd;
302 long ret;
303
304 if (d.mm < TISHREI)
305 {
306 for (m = TISHREI; m <= MONTHS_IN_HEB (d.yy); m++)
307 tempabs += (long) max_days_in_heb_month (m, d.yy);
308
309 for (m = NISAN; m < d.mm; m++)
310 tempabs += (long) max_days_in_heb_month (m, d.yy);
311 }
312 else
313 {
314 for (m = TISHREI; m < d.mm; m++)
315 tempabs += (long) max_days_in_heb_month (m, d.yy);
316 }
317
318
319 ret = hebrew_elapsed_days (d.yy) - 1373429L + tempabs;
320 return ret;
321 }
322
323 /* Number of days in the hebrew YEAR */
days_in_heb_year(int year)324 int days_in_heb_year( int year )
325 {
326 return (int) (hebrew_elapsed_days (year + 1) - hebrew_elapsed_days (year));
327 }
328
329 /* true if Cheshvan is long in hebrew YEAR */
long_cheshvan(int year)330 int long_cheshvan( int year )
331 {
332 return ((days_in_heb_year (year) % 10) == 5);
333 }
334
335 /* true if Cheshvan is long in hebrew YEAR */
short_kislev(int year)336 int short_kislev( int year )
337 {
338 return ((days_in_heb_year (year) % 10) == 3);
339 }
340