File indexing completed on 2025-01-19 04:46:46
0001 /* 0002 This file is part of KOrganizer. 0003 0004 SPDX-FileCopyrightText: 2003 Jonathan Singer <jsinger@leeta.net> 0005 SPDX-FileCopyrightText: 2007 Loïc Corbasson <loic.corbasson@gmail.com> 0006 0007 Calendar routines from Hebrew Calendar by Frank Yellin. 0008 Based on some GNU Emacs code (lisp/calendar/cal-hebrew.el), 0009 SPDX-FileCopyrightText: 1995, 1997 Free Software Foundation, Inc. 0010 SPDX-FileContributor: Nachum Dershowitz <nachum@cs.uiuc.edu> 0011 SPDX-FileContributor: Edward M. Reingold <reingold@cs.uiuc.edu> 0012 0013 SPDX-License-Identifier: GPL-2.0-or-later 0014 */ 0015 0016 #include "holiday.h" 0017 #include "parsha.h" 0018 0019 #include <KLocalizedString> 0020 0021 QStringList Holiday::findHoliday(const HebrewDate &hd, bool useIsraelSettings, bool showParsha, bool showChol, bool showOmer) 0022 { 0023 return findHoliday(hd.month(), 0024 hd.day(), 0025 hd.dayOfWeek() + 1, 0026 hd.kvia(), 0027 hd.isOnHebrewLeapYear(), 0028 useIsraelSettings, 0029 hd.hebrewDayNumber(), 0030 hd.year(), 0031 showParsha, 0032 showChol, 0033 showOmer); 0034 } 0035 0036 QStringList Holiday::findHoliday(int month, 0037 int day, 0038 int weekday, 0039 int kvia, 0040 bool isLeapYear, 0041 bool useIsraelSettings, 0042 int dayNumber, 0043 int year, 0044 bool showParsha, 0045 bool showChol, 0046 bool showOmer) 0047 { 0048 enum { 0049 Sunday = 1, 0050 Monday, 0051 Tuesday, 0052 Wednesday, 0053 Thursday, 0054 Friday, 0055 Saturday, 0056 }; 0057 0058 QStringList holidays; 0059 bool isAShabbat = (weekday == Saturday); 0060 0061 // Treat Adar in a non-leap year as if it were Adar II. 0062 if ((month == Adar) && !isLeapYear) { 0063 month = AdarII; 0064 } 0065 switch (month) { 0066 case Nissan: 0067 switch (day) { 0068 case 1: 0069 if (isAShabbat) { 0070 holidays << i18nc( 0071 "These are Jewish holidays and mostly do not " 0072 "have translations. They may have different " 0073 "spellings in your language; otherwise, just " 0074 "translate the sound to your characters.", 0075 "Sh. HaHodesh"); 0076 } 0077 break; 0078 case 14: 0079 if (!isAShabbat) { 0080 // If it's Shabbat, we have three pieces of info. 0081 // This is the least important, so we skip it on Shabbat as we only 0082 // really want the two most important ones. 0083 holidays << i18n("Erev Pesach"); 0084 } 0085 /* fall through */ 0086 case 8: 0087 case 9: 0088 case 10: 0089 case 11: 0090 case 12: 0091 case 13: 0092 // The Saturday before Pesach (8th-14th) 0093 if (isAShabbat) { 0094 holidays << i18n("Sh. HaGadol"); 0095 } 0096 break; 0097 case 15: 0098 case 16: 0099 case 21: 0100 case 22: 0101 if (!useIsraelSettings || (day == 15) || (day == 21)) { 0102 holidays << i18n("Pesach"); 0103 break; 0104 } else if (day == 22) { 0105 break; 0106 } 0107 /* else fall through */ 0108 case 17: 0109 case 18: 0110 case 19: 0111 case 20: 0112 if (showChol) { 0113 holidays << i18n("Chol Hamoed"); 0114 } 0115 break; 0116 case 26: 0117 case 27: 0118 case 28: 0119 // Yom HaShoah only exists since Israel was established. 0120 if (year > 1948 + 3760) { 0121 switch (weekday) { 0122 case Thursday: 0123 if (day == 26 || day == 27) { 0124 holidays << i18n("Yom HaShoah"); 0125 } 0126 break; 0127 case Monday: 0128 if (day == 28 || day == 27) { 0129 holidays << i18n("Yom HaShoah"); 0130 } 0131 break; 0132 case Sunday: 0133 case Friday: 0134 // These are never either of them. 0135 break; 0136 default: 0137 if (day == 27) { 0138 holidays << i18n("Yom HaShoah"); 0139 } 0140 break; 0141 } 0142 } 0143 break; 0144 } 0145 if ((day > 15) && showOmer) { 0146 // Count the Omer, starting after the first day of Pesach. 0147 holidays << sfirah(day - 15); 0148 } 0149 break; 0150 0151 case Iyar: 0152 switch (day) { 0153 case 2: 0154 case 3: 0155 case 4: 0156 case 5: 0157 // Yom HaAtzmaut is on the 5th, unless that's a Saturday, in which 0158 // case it is moved back two days to Thursday. Yom HaZikaron is the 0159 // day before Yom HaAtzmaut. 0160 if (year >= 1948 + 3760) { // only after Israel was established 0161 switch (weekday) { 0162 case Wednesday: 0163 if (day == 5) { 0164 holidays << i18n("Yom HaAtzmaut"); 0165 } else { 0166 holidays << i18n("Yom HaZikaron"); 0167 } 0168 break; 0169 case Thursday: 0170 // This can't be 2 Iyar. 0171 holidays << i18n("Yom HaAtzmaut"); 0172 break; 0173 case Friday: 0174 case Saturday: 0175 // These are never either of them. 0176 break; 0177 default: 0178 // All other days follow the normal rules. 0179 if (day == 4) { 0180 holidays << i18n("Yom HaZikaron"); 0181 } else if (day == 5) { 0182 holidays << i18n("Yom HaAtzmaut"); 0183 } 0184 } 0185 } 0186 break; 0187 case 28: 0188 if (year > 1967 + 3760) { 0189 // only since the 1967 war 0190 holidays << i18n("Yom Yerushalayim"); 0191 } 0192 break; 0193 case 18: 0194 holidays << i18n("Lag BaOmer"); 0195 break; 0196 } 0197 if ((day != 18) && showOmer) { 0198 // Sfirah the whole month, Lag BaOmer is already mentioned. 0199 holidays << sfirah(day + 15); 0200 } 0201 break; 0202 0203 case Sivan: 0204 switch (day) { 0205 case 1: 0206 case 2: 0207 case 3: 0208 case 4: 0209 // Sfirah until Shavuot 0210 if (showOmer) { 0211 holidays << sfirah(day + 44); 0212 } 0213 break; 0214 case 5: 0215 // Don't need to mention Sfira(49) if there's already two other and 0216 // more important pieces of information. 0217 if (showOmer && !isAShabbat) { 0218 holidays << sfirah(49); 0219 } 0220 holidays << i18n("Erev Shavuot"); 0221 break; 0222 case 6:; 0223 case 7: 0224 if (!useIsraelSettings || (day == 6)) { 0225 holidays << i18n("Shavuot"); 0226 } 0227 break; 0228 } 0229 break; 0230 0231 case Tamuz: 0232 // 17th of Tamuz, except Shabbat pushes it to Sunday. 0233 if ((!isAShabbat && (day == 17)) || ((weekday == Sunday) && (day == 18))) { 0234 holidays << i18n("Tzom Tammuz"); 0235 } 0236 break; 0237 0238 case Ab: 0239 if (isAShabbat && (3 <= day) && (day <= 16)) { 0240 // The shabbat before and after Tisha B'Av are special 0241 if (day <= 9) { 0242 holidays << i18n("Sh. Hazon"); 0243 } else { 0244 holidays << i18n("Sh. Nahamu"); 0245 } 0246 } else if ((!isAShabbat && (day == 9)) || ((weekday == Sunday) && (day == 10))) { 0247 // 9th of Av, except Shabbat pushes it to Sunday. 0248 holidays << i18n("Tisha B'Av"); 0249 } 0250 break; 0251 0252 case Elul: 0253 if ((day >= 20) && (day <= 26) && isAShabbat) { 0254 holidays << i18n("S'lichot"); 0255 } else if (day == 29) { 0256 holidays << i18n("Erev R.H."); 0257 } 0258 break; 0259 0260 case Tishrei: 0261 switch (day) { 0262 case 1:; 0263 case 2: 0264 holidays << i18n("Rosh Hashana"); 0265 break; 0266 case 3: 0267 if (isAShabbat) { 0268 holidays << i18n("Sh. Shuvah"); 0269 } else { 0270 holidays << i18n("Tzom Gedalia"); 0271 } 0272 break; 0273 case 4: 0274 if (weekday == Sunday) { 0275 holidays << i18n("Tzom Gedalia"); 0276 } 0277 /* fall through */ 0278 case 5: 0279 case 6: 0280 case 7: 0281 case 8: 0282 if (isAShabbat) { 0283 holidays << i18n("Sh. Shuvah"); 0284 } 0285 break; 0286 case 9: 0287 holidays << i18n("Erev Y.K."); 0288 break; 0289 case 10: 0290 holidays << i18n("Yom Kippur"); 0291 break; 0292 case 14: 0293 holidays << i18n("Erev Sukkot"); 0294 break; 0295 case 15: 0296 case 16: 0297 if (!useIsraelSettings || (day == 15)) { 0298 holidays << i18n("Sukkot"); 0299 break; 0300 } 0301 /* else fall through */ 0302 case 17: 0303 case 18: 0304 case 19: 0305 case 20: 0306 if (showChol) { 0307 holidays << i18n("Chol Hamoed"); 0308 } 0309 break; 0310 case 21: 0311 holidays << i18n("Hoshana Rabah"); 0312 break; 0313 case 22: 0314 holidays << i18n("Shmini Atzeret"); 0315 break; 0316 case 23: 0317 if (!useIsraelSettings) { 0318 holidays << i18n("Simchat Torah"); 0319 } 0320 break; 0321 } 0322 break; 0323 0324 case Cheshvan: 0325 break; 0326 0327 case Kislev: 0328 if (day == 24) { 0329 holidays << i18n("Erev Hanukah"); 0330 } else if (day >= 25) { 0331 holidays << i18n("Hanukah"); 0332 } 0333 break; 0334 0335 case Tevet: 0336 if (day <= (kvia == 0 ? 3 : 2)) { 0337 // We need to know the length of Kislev to determine the last day of 0338 // Chanukah. 0339 holidays << i18n("Hanukah"); 0340 } else if (((day == 10) && !isAShabbat) || ((day == 11) && (weekday == Sunday))) { 0341 // 10th of Tevet; Shabbat pushes it to Sunday. 0342 holidays << i18n("Tzom Tevet"); 0343 } 0344 break; 0345 0346 case Shvat: 0347 switch (day) { 0348 // The info for figuring out Shabbat Shirah is from the Gnu code. I 0349 // assume it's correct. 0350 case 10: 0351 if ((kvia != 0) && isAShabbat) { 0352 holidays << i18n("Sh. Shirah"); 0353 } 0354 break; 0355 case 11: 0356 case 12: 0357 case 13: 0358 case 14: 0359 case 16: 0360 if (isAShabbat) { 0361 holidays << i18n("Sh. Shirah"); 0362 } 0363 break; 0364 case 15: 0365 if (isAShabbat) { 0366 holidays << i18n("Sh. Shirah"); 0367 } 0368 holidays << i18n("Tu B'Shvat"); 0369 break; 0370 case 17: 0371 if ((kvia == 0) && isAShabbat) { 0372 holidays << i18n("Sh. Shirah"); 0373 } 0374 break; 0375 case 25: 0376 case 26: 0377 case 27: 0378 case 28: 0379 case 29: 0380 case 30: 0381 // The last shabbat on or before 1 Adar or 1 AdarII 0382 if (isAShabbat && !isLeapYear) { 0383 holidays << i18n("Sh. Shekalim"); 0384 } 0385 break; 0386 } 0387 break; 0388 0389 case AdarI: 0390 if (day == 14) { 0391 // Eat Purim Katan Candy 0392 holidays << i18n("Purim Katan"); 0393 } else if ((day >= 25) && isAShabbat) { 0394 // The last shabbat on or before 1 Adar II. 0395 holidays << i18n("Sh. Shekalim"); 0396 } 0397 break; 0398 0399 case AdarII: /* Adar II or non-leap year Adar */ 0400 switch (day) { 0401 case 1: 0402 if (isAShabbat) { 0403 holidays << i18n("Sh. Shekalim"); 0404 } 0405 break; 0406 case 11: 0407 case 12: 0408 // Ta'anit ester is on the 13th. But shabbat moves it back to 0409 // Thursday. 0410 if (weekday == Thursday) { 0411 holidays << i18n("Ta'anit Ester"); 0412 } 0413 /* fall through */ 0414 case 7: 0415 case 8: 0416 case 9: 0417 case 10: 0418 // The Shabbat before purim is Shabbat Zachor 0419 if (isAShabbat) { 0420 holidays << i18n("Sh. Zachor"); 0421 } 0422 break; 0423 case 13: 0424 if (isAShabbat) { 0425 holidays << i18n("Sh. Zachor"); 0426 } else { 0427 holidays << i18n("Erev Purim"); 0428 } 0429 // It's Ta'anit Esther, unless it's a Friday or Saturday 0430 if (weekday < Friday) { 0431 holidays << i18n("Ta'anit Ester"); 0432 } 0433 break; 0434 case 14: 0435 holidays << i18n("Purim"); 0436 break; 0437 case 15: 0438 if (!isAShabbat) { 0439 holidays << i18n("Shushan Purim"); 0440 } 0441 break; 0442 case 16: 0443 if (weekday == Sunday) { 0444 holidays << i18n("Shushan Purim"); 0445 } 0446 break; 0447 case 17: 0448 case 18: 0449 case 19: 0450 case 20: 0451 case 21: 0452 case 22: 0453 case 23: 0454 if (isAShabbat) { 0455 holidays << i18n("Sh. Parah"); 0456 } 0457 break; 0458 case 24: 0459 case 25: 0460 case 26: 0461 case 27: 0462 case 28: 0463 case 29: 0464 if (isAShabbat) { 0465 holidays << i18n("Sh. HaHodesh"); 0466 } 0467 break; 0468 } 0469 break; 0470 } 0471 if (isAShabbat && showParsha) { 0472 // Find the Parsha on Shabbat. 0473 holidays << Parsha::findParshaName(dayNumber, kvia, isLeapYear, useIsraelSettings); 0474 } 0475 return holidays; 0476 } 0477 0478 QString Holiday::sfirah(int day) 0479 { 0480 QString buffer = QString::number(day); 0481 buffer + i18n(" Omer"); // TODO: Find a way to write 1st instead of 1, 0482 // 2nd instead of 2, etc. 0483 return buffer; 0484 }