1 /*
2 This file is part of KOrganizer.
3
4 SPDX-FileCopyrightText: 2003 Jonathan Singer <jsinger@leeta.net>
5 SPDX-FileCopyrightText: 2007 Loïc Corbasson <loic.corbasson@gmail.com>
6
7 Calendar routines from Hebrew Calendar by Frank Yellin.
8 Based on some GNU Emacs code (lisp/calendar/cal-hebrew.el),
9 SPDX-FileCopyrightText: 1995, 1997 Free Software Foundation, Inc.
10 SPDX-FileContributor: Nachum Dershowitz <nachum@cs.uiuc.edu>
11 SPDX-FileContributor: Edward M. Reingold <reingold@cs.uiuc.edu>
12
13 SPDX-License-Identifier: GPL-2.0-or-later
14 */
15
16 #include "holiday.h"
17 #include "parsha.h"
18
19 #include <KLocalizedString>
20
findHoliday(const HebrewDate & hd,bool useIsraelSettings,bool showParsha,bool showChol,bool showOmer)21 QStringList Holiday::findHoliday(const HebrewDate &hd, bool useIsraelSettings, bool showParsha, bool showChol, bool showOmer)
22 {
23 return findHoliday(hd.month(),
24 hd.day(),
25 hd.dayOfWeek() + 1,
26 hd.kvia(),
27 hd.isOnHebrewLeapYear(),
28 useIsraelSettings,
29 hd.hebrewDayNumber(),
30 hd.year(),
31 showParsha,
32 showChol,
33 showOmer);
34 }
35
findHoliday(int month,int day,int weekday,int kvia,bool isLeapYear,bool useIsraelSettings,int dayNumber,int year,bool showParsha,bool showChol,bool showOmer)36 QStringList Holiday::findHoliday(int month,
37 int day,
38 int weekday,
39 int kvia,
40 bool isLeapYear,
41 bool useIsraelSettings,
42 int dayNumber,
43 int year,
44 bool showParsha,
45 bool showChol,
46 bool showOmer)
47 {
48 enum {
49 Sunday = 1,
50 Monday,
51 Tuesday,
52 Wednesday,
53 Thursday,
54 Friday,
55 Saturday,
56 };
57
58 QStringList holidays;
59 bool isAShabbat = (weekday == Saturday);
60
61 // Treat Adar in a non-leap year as if it were Adar II.
62 if ((month == Adar) && !isLeapYear) {
63 month = AdarII;
64 }
65 switch (month) {
66 case Nissan:
67 switch (day) {
68 case 1:
69 if (isAShabbat) {
70 holidays << i18nc(
71 "These are Jewish holidays and mostly do not "
72 "have translations. They may have different "
73 "spellings in your language; otherwise, just "
74 "translate the sound to your characters.",
75 "Sh. HaHodesh");
76 }
77 break;
78 case 14:
79 if (!isAShabbat) {
80 // If it's Shabbat, we have three pieces of info.
81 // This is the least important, so we skip it on Shabbat as we only
82 // really want the two most important ones.
83 holidays << i18n("Erev Pesach");
84 }
85 /* fall through */
86 case 8:
87 case 9:
88 case 10:
89 case 11:
90 case 12:
91 case 13:
92 // The Saturday before Pesach (8th-14th)
93 if (isAShabbat) {
94 holidays << i18n("Sh. HaGadol");
95 }
96 break;
97 case 15:
98 case 16:
99 case 21:
100 case 22:
101 if (!useIsraelSettings || (day == 15) || (day == 21)) {
102 holidays << i18n("Pesach");
103 break;
104 } else if (day == 22) {
105 break;
106 }
107 /* else fall through */
108 case 17:
109 case 18:
110 case 19:
111 case 20:
112 if (showChol) {
113 holidays << i18n("Chol Hamoed");
114 }
115 break;
116 case 26:
117 case 27:
118 case 28:
119 // Yom HaShoah only exists since Israel was established.
120 if (year > 1948 + 3760) {
121 switch (weekday) {
122 case Thursday:
123 if (day == 26 || day == 27) {
124 holidays << i18n("Yom HaShoah");
125 }
126 break;
127 case Monday:
128 if (day == 28 || day == 27) {
129 holidays << i18n("Yom HaShoah");
130 }
131 break;
132 case Sunday:
133 case Friday:
134 // These are never either of them.
135 break;
136 default:
137 if (day == 27) {
138 holidays << i18n("Yom HaShoah");
139 }
140 break;
141 }
142 }
143 break;
144 }
145 if ((day > 15) && showOmer) {
146 // Count the Omer, starting after the first day of Pesach.
147 holidays << sfirah(day - 15);
148 }
149 break;
150
151 case Iyar:
152 switch (day) {
153 case 2:
154 case 3:
155 case 4:
156 case 5:
157 // Yom HaAtzmaut is on the 5th, unless that's a Saturday, in which
158 // case it is moved back two days to Thursday. Yom HaZikaron is the
159 // day before Yom HaAtzmaut.
160 if (year >= 1948 + 3760) { // only after Israel was established
161 switch (weekday) {
162 case Wednesday:
163 if (day == 5) {
164 holidays << i18n("Yom HaAtzmaut");
165 } else {
166 holidays << i18n("Yom HaZikaron");
167 }
168 break;
169 case Thursday:
170 // This can't be 2 Iyar.
171 holidays << i18n("Yom HaAtzmaut");
172 break;
173 case Friday:
174 case Saturday:
175 // These are never either of them.
176 break;
177 default:
178 // All other days follow the normal rules.
179 if (day == 4) {
180 holidays << i18n("Yom HaZikaron");
181 } else if (day == 5) {
182 holidays << i18n("Yom HaAtzmaut");
183 }
184 }
185 }
186 break;
187 case 28:
188 if (year > 1967 + 3760) {
189 // only since the 1967 war
190 holidays << i18n("Yom Yerushalayim");
191 }
192 break;
193 case 18:
194 holidays << i18n("Lag BaOmer");
195 break;
196 }
197 if ((day != 18) && showOmer) {
198 // Sfirah the whole month, Lag BaOmer is already mentioned.
199 holidays << sfirah(day + 15);
200 }
201 break;
202
203 case Sivan:
204 switch (day) {
205 case 1:
206 case 2:
207 case 3:
208 case 4:
209 // Sfirah until Shavuot
210 if (showOmer) {
211 holidays << sfirah(day + 44);
212 }
213 break;
214 case 5:
215 // Don't need to mention Sfira(49) if there's already two other and
216 // more important pieces of information.
217 if (showOmer && !isAShabbat) {
218 holidays << sfirah(49);
219 }
220 holidays << i18n("Erev Shavuot");
221 break;
222 case 6:;
223 case 7:
224 if (!useIsraelSettings || (day == 6)) {
225 holidays << i18n("Shavuot");
226 }
227 break;
228 }
229 break;
230
231 case Tamuz:
232 // 17th of Tamuz, except Shabbat pushes it to Sunday.
233 if ((!isAShabbat && (day == 17)) || ((weekday == Sunday) && (day == 18))) {
234 holidays << i18n("Tzom Tammuz");
235 }
236 break;
237
238 case Ab:
239 if (isAShabbat && (3 <= day) && (day <= 16)) {
240 // The shabbat before and after Tisha B'Av are special
241 if (day <= 9) {
242 holidays << i18n("Sh. Hazon");
243 } else {
244 holidays << i18n("Sh. Nahamu");
245 }
246 } else if ((!isAShabbat && (day == 9)) || ((weekday == Sunday) && (day == 10))) {
247 // 9th of Av, except Shabbat pushes it to Sunday.
248 holidays << i18n("Tisha B'Av");
249 }
250 break;
251
252 case Elul:
253 if ((day >= 20) && (day <= 26) && isAShabbat) {
254 holidays << i18n("S'lichot");
255 } else if (day == 29) {
256 holidays << i18n("Erev R.H.");
257 }
258 break;
259
260 case Tishrei:
261 switch (day) {
262 case 1:;
263 case 2:
264 holidays << i18n("Rosh Hashana");
265 break;
266 case 3:
267 if (isAShabbat) {
268 holidays << i18n("Sh. Shuvah");
269 } else {
270 holidays << i18n("Tzom Gedalia");
271 }
272 break;
273 case 4:
274 if (weekday == Sunday) {
275 holidays << i18n("Tzom Gedalia");
276 }
277 /* fall through */
278 case 5:
279 case 6:
280 case 7:
281 case 8:
282 if (isAShabbat) {
283 holidays << i18n("Sh. Shuvah");
284 }
285 break;
286 case 9:
287 holidays << i18n("Erev Y.K.");
288 break;
289 case 10:
290 holidays << i18n("Yom Kippur");
291 break;
292 case 14:
293 holidays << i18n("Erev Sukkot");
294 break;
295 case 15:
296 case 16:
297 if (!useIsraelSettings || (day == 15)) {
298 holidays << i18n("Sukkot");
299 break;
300 }
301 /* else fall through */
302 case 17:
303 case 18:
304 case 19:
305 case 20:
306 if (showChol) {
307 holidays << i18n("Chol Hamoed");
308 }
309 break;
310 case 21:
311 holidays << i18n("Hoshana Rabah");
312 break;
313 case 22:
314 holidays << i18n("Shmini Atzeret");
315 break;
316 case 23:
317 if (!useIsraelSettings) {
318 holidays << i18n("Simchat Torah");
319 }
320 break;
321 }
322 break;
323
324 case Cheshvan:
325 break;
326
327 case Kislev:
328 if (day == 24) {
329 holidays << i18n("Erev Hanukah");
330 } else if (day >= 25) {
331 holidays << i18n("Hanukah");
332 }
333 break;
334
335 case Tevet:
336 if (day <= (kvia == 0 ? 3 : 2)) {
337 // We need to know the length of Kislev to determine the last day of
338 // Chanukah.
339 holidays << i18n("Hanukah");
340 } else if (((day == 10) && !isAShabbat) || ((day == 11) && (weekday == Sunday))) {
341 // 10th of Tevet; Shabbat pushes it to Sunday.
342 holidays << i18n("Tzom Tevet");
343 }
344 break;
345
346 case Shvat:
347 switch (day) {
348 // The info for figuring out Shabbat Shirah is from the Gnu code. I
349 // assume it's correct.
350 case 10:
351 if ((kvia != 0) && isAShabbat) {
352 holidays << i18n("Sh. Shirah");
353 }
354 break;
355 case 11:
356 case 12:
357 case 13:
358 case 14:
359 case 16:
360 if (isAShabbat) {
361 holidays << i18n("Sh. Shirah");
362 }
363 break;
364 case 15:
365 if (isAShabbat) {
366 holidays << i18n("Sh. Shirah");
367 }
368 holidays << i18n("Tu B'Shvat");
369 break;
370 case 17:
371 if ((kvia == 0) && isAShabbat) {
372 holidays << i18n("Sh. Shirah");
373 }
374 break;
375 case 25:
376 case 26:
377 case 27:
378 case 28:
379 case 29:
380 case 30:
381 // The last shabbat on or before 1 Adar or 1 AdarII
382 if (isAShabbat && !isLeapYear) {
383 holidays << i18n("Sh. Shekalim");
384 }
385 break;
386 }
387 break;
388
389 case AdarI:
390 if (day == 14) {
391 // Eat Purim Katan Candy
392 holidays << i18n("Purim Katan");
393 } else if ((day >= 25) && isAShabbat) {
394 // The last shabbat on or before 1 Adar II.
395 holidays << i18n("Sh. Shekalim");
396 }
397 break;
398
399 case AdarII: /* Adar II or non-leap year Adar */
400 switch (day) {
401 case 1:
402 if (isAShabbat) {
403 holidays << i18n("Sh. Shekalim");
404 }
405 break;
406 case 11:
407 case 12:
408 // Ta'anit ester is on the 13th. But shabbat moves it back to
409 // Thursday.
410 if (weekday == Thursday) {
411 holidays << i18n("Ta'anit Ester");
412 }
413 /* fall through */
414 case 7:
415 case 8:
416 case 9:
417 case 10:
418 // The Shabbat before purim is Shabbat Zachor
419 if (isAShabbat) {
420 holidays << i18n("Sh. Zachor");
421 }
422 break;
423 case 13:
424 if (isAShabbat) {
425 holidays << i18n("Sh. Zachor");
426 } else {
427 holidays << i18n("Erev Purim");
428 }
429 // It's Ta'anit Esther, unless it's a Friday or Saturday
430 if (weekday < Friday) {
431 holidays << i18n("Ta'anit Ester");
432 }
433 break;
434 case 14:
435 holidays << i18n("Purim");
436 break;
437 case 15:
438 if (!isAShabbat) {
439 holidays << i18n("Shushan Purim");
440 }
441 break;
442 case 16:
443 if (weekday == Sunday) {
444 holidays << i18n("Shushan Purim");
445 }
446 break;
447 case 17:
448 case 18:
449 case 19:
450 case 20:
451 case 21:
452 case 22:
453 case 23:
454 if (isAShabbat) {
455 holidays << i18n("Sh. Parah");
456 }
457 break;
458 case 24:
459 case 25:
460 case 26:
461 case 27:
462 case 28:
463 case 29:
464 if (isAShabbat) {
465 holidays << i18n("Sh. HaHodesh");
466 }
467 break;
468 }
469 break;
470 }
471 if (isAShabbat && showParsha) {
472 // Find the Parsha on Shabbat.
473 holidays << Parsha::findParshaName(dayNumber, kvia, isLeapYear, useIsraelSettings);
474 }
475 return holidays;
476 }
477
sfirah(int day)478 QString Holiday::sfirah(int day)
479 {
480 QString buffer = QString::number(day);
481 buffer + i18n(" Omer"); // TODO: Find a way to write 1st instead of 1,
482 // 2nd instead of 2, etc.
483 return buffer;
484 }
485