File indexing completed on 2025-01-05 04:49:35

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 "parsha.h"
0017 #include "korganizer_hebrew_debug.h"
0018 #include <KLocalizedString>
0019 
0020 QString Parsha::findParshaName(int dayNumber, int kvia, bool isLeapYear, bool useIsraelSettings)
0021 {
0022     // The names of the Parshiot.
0023     static QStringList parshiotNames = QStringList();
0024     parshiotNames << i18nc(
0025         "These are weekly readings and do not have translations. "
0026         "They may have different spellings in your language; "
0027         "otherwise, just translate the sound to your characters",
0028         "Bereshit")
0029                   << i18n("Noach") << i18n("Lech L'cha") << i18n("Vayera") << i18n("Chaye Sarah") << i18n("Toldot") << i18n("Vayetze") << i18n("Vayishlach")
0030                   << i18n("Vayeshev") << i18n("Miketz") << i18n("Vayigash") << i18n("Vayechi") << i18n("Shemot") << i18n("Vaera") << i18n("Bo")
0031                   << i18n("Beshalach") << i18n("Yitro") << i18n("Mishpatim") << i18n("Terumah") << i18n("Tetzaveh") << i18n("Ki Tisa") << i18n("Vayakhel")
0032                   << i18n("Pekudei") << i18n("Vayikra") << i18n("Tzav") << i18n("Shemini") << i18n("Tazria") << i18n("Metzora") << i18n("Acharei Mot")
0033                   << i18n("Kedoshim") << i18n("Emor") << i18n("Behar") << i18n("Bechukotai") << i18n("Bemidbar") << i18n("Naso") << i18n("Behaalotcha")
0034                   << i18n("Shelach") << i18n("Korach") << i18n("Chukat") << i18n("Balak") << i18n("Pinchas") << i18n("Matot") << i18n("Masei")
0035                   << i18n("Devarim") << i18n("Vaetchanan") << i18n("Ekev") << i18n("Reeh") << i18n("Shoftim") << i18n("Ki Tetze") << i18n("Ki Tavo")
0036                   << i18n("Nitzavim") << i18n("Vayelech") << i18n("Haazinu");
0037 
0038     /*
0039       Tables for each of the year types. XX indicates that it is a Holiday, and a
0040       special parsha is read that week. For some year types among the 14, Israel
0041       is different from the diaspora.
0042 
0043       The names indicate the day of the week on which Rosh Hashanah fell, whether
0044       it is a short/normal/long year (kvia=0,1,2), and whether it is a leap year.
0045       As said earlier, some year types also have an _Israel version.
0046 
0047       The numbers are indices in the list above for a given week.
0048       Numbers > 100 indicate a double parsha, e.g. 150 means read both table
0049       entries 150 - 100 = 50 and 150 - 99 = 51.
0050 
0051       These tables were stolen (with some massaging) from the Gnu code.
0052     */
0053 
0054     static const quint8 XX = 255;
0055 
0056     /* Non-leap years */
0057     static const quint8 SatShort[] = {
0058         XX, 52, XX, XX, 0,   1,   2,  3,   4,  5,  6,  7,  8,  9,  10, 11, 12,  13, 14, 15, 16, 17, 18, 19, 20, 121,
0059         23, 24, XX, 25, 126, 128, 30, 131, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 50,
0060     };
0061     static const quint8 SatLong[] = {
0062         XX, 52, XX, XX, 0,   1,   2,  3,   4,  5,  6,  7,  8,  9,  10, 11, 12,  13, 14, 15, 16, 17, 18, 19, 20,  121,
0063         23, 24, XX, 25, 126, 128, 30, 131, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 150,
0064     };
0065 
0066     static const quint8 MonShort[] = {
0067         51, 52, XX, 0,  1,   2,   3,  4,   5,  6,  7,  8,  9,  10, 11, 12, 13,  14, 15, 16, 17, 18, 19, 20, 121,
0068         23, 24, XX, 25, 126, 128, 30, 131, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 150,
0069     };
0070     static const quint8 MonLong[] = /* split */
0071         {
0072             51, 52, XX, 0,  1,   2,   3,  4,   5,  6,  7,  8,  9,  10, 11,  12, 13,  14, 15, 16, 17, 18, 19, 20, 121,
0073             23, 24, XX, 25, 126, 128, 30, 131, 33, XX, 34, 35, 36, 37, 138, 40, 141, 43, 44, 45, 46, 47, 48, 49, 150,
0074         };
0075 #define MonLong_Israel MonShort
0076 
0077 #define TueNormal MonLong
0078 #define TueNormal_Israel MonShort
0079 
0080     static const quint8 ThuNormal[] = {
0081         52, XX, XX, 0,  1,   2,   3,  4,   5,  6,  7,  8,  9,  10, 11, 12, 13,  14, 15, 16, 17, 18, 19, 20, 121, 23,
0082         24, XX, XX, 25, 126, 128, 30, 131, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 50,
0083     };
0084     static const quint8 ThuNormal_Israel[] = {
0085         52, XX, XX, 0,   1,   2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13,  14, 15, 16, 17, 18, 19, 20, 121, 23,
0086         24, XX, 25, 126, 128, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 50,
0087     };
0088     static const quint8 ThuLong[] = {
0089         52, XX, XX, 0,  1,   2,   3,  4,   5,  6,  7,  8,  9,  10, 11, 12, 13,  14, 15, 16, 17, 18, 19, 20, 21, 22,
0090         23, 24, XX, 25, 126, 128, 30, 131, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 50,
0091     };
0092 
0093     /* Leap years */
0094     static const quint8 SatShortLeap[] = {
0095         XX, 52, XX, XX, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,  15, 16, 17, 18, 19, 20, 21, 22,  23,
0096         24, 25, 26, 27, XX, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 150,
0097     };
0098     static const quint8 SatLongLeap[] = {
0099         XX, 52, XX, XX, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12,  13, 14,  15, 16, 17, 18, 19, 20, 21, 22,  23,
0100         24, 25, 26, 27, XX, 28, 29, 30, 31, 32, 33, XX, 34, 35, 36, 37, 138, 40, 141, 43, 44, 45, 46, 47, 48, 49, 150,
0101     };
0102 #define SatLongLeap_Israel SatShortLeap
0103 
0104     static const quint8 MonShortLeap[] = {
0105         51, 52, XX, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13,  14, 15,  16, 17, 18, 19, 20, 21, 22, 23,
0106         24, 25, 26, 27, XX, 28, 29, 30, 31, 32, 33, XX, 34, 35, 36, 37, 138, 40, 141, 43, 44, 45, 46, 47, 48, 49, 150,
0107     };
0108     static const quint8 MonShortLeap_Israel[] = {
0109         51, 52, XX, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,  16, 17, 18, 19, 20, 21, 22, 23,
0110         24, 25, 26, 27, XX, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 150,
0111     };
0112     static const quint8 MonLongLeap[] = {
0113         51, 52, XX, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,  16, 17, 18, 19, 20, 21, 22, 23, 24,
0114         25, 26, 27, XX, XX, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 141, 43, 44, 45, 46, 47, 48, 49, 50,
0115     };
0116     static const quint8 MonLongLeap_Israel[] = {
0117         51, 52, XX, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
0118         25, 26, 27, XX, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
0119     };
0120 
0121 #define TueNormalLeap MonLongLeap
0122 #define TueNormalLeap_Israel MonLongLeap_Israel
0123 
0124     static const quint8 ThuShortLeap[] = {
0125         52, XX, XX, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
0126         25, 26, 27, 28, XX, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
0127     };
0128     static const quint8 ThuLongLeap[] = {
0129         52, XX, XX, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,  24,
0130         25, 26, 27, 28, XX, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 150,
0131     };
0132 
0133     /* Make the calculations */
0134     int week = dayNumber / 7; // week of the year
0135     const quint8 *array = nullptr;
0136     int index;
0137 
0138     /* Get the appropriate array by exhaustive search into the 14 year types.
0139        Since we know it's a Shabbat, we can find out what day Rosh Hashanah was on
0140        by looking at dayNumber % 7. */
0141     if (!isLeapYear) {
0142         switch (dayNumber % 7) {
0143         case 1: /* Rosh Hashanah was on a Saturday */
0144             if (kvia == 0) {
0145                 array = SatShort;
0146             } else if (kvia == 2) {
0147                 array = SatLong;
0148             }
0149             break;
0150         case 6: /* Rosh Hashanah was on a Monday */
0151             if (kvia == 0) {
0152                 array = MonShort;
0153             } else if (kvia == 2) {
0154                 array = useIsraelSettings ? MonLong_Israel : MonLong;
0155             }
0156             break;
0157         case 5: /* Rosh Hashanah was on a Tuesday */
0158             if (kvia == 1) {
0159                 array = useIsraelSettings ? TueNormal_Israel : TueNormal;
0160             }
0161             break;
0162         case 3: /* Rosh Hashanah was on a Thursday */
0163             if (kvia == 1) {
0164                 array = useIsraelSettings ? ThuNormal_Israel : ThuNormal;
0165             } else if (kvia == 2) {
0166                 array = ThuLong;
0167             }
0168             break;
0169         }
0170     } else { /* leap year */
0171         switch (dayNumber % 7) {
0172         case 1: /* Rosh Hashanah was on a Sat */
0173             if (kvia == 0) {
0174                 array = SatShortLeap;
0175             } else if (kvia == 2) {
0176                 array = useIsraelSettings ? SatLongLeap_Israel : SatLongLeap;
0177             }
0178             break;
0179         case 6: /* Rosh Hashanah was on a Monday */
0180             if (kvia == 0) {
0181                 array = useIsraelSettings ? MonShortLeap_Israel : MonShortLeap;
0182             } else if (kvia == 2) {
0183                 array = useIsraelSettings ? MonLongLeap_Israel : MonLongLeap;
0184             }
0185             break;
0186         case 5: /* Rosh Hashanah was on a Tuesday */
0187             if (kvia == 1) {
0188                 array = useIsraelSettings ? TueNormalLeap_Israel : TueNormalLeap;
0189             }
0190             break;
0191         case 3: /* Rosh Hashanah was on a Thursday */
0192             if (kvia == 0) {
0193                 array = ThuShortLeap;
0194             } else if (kvia == 2) {
0195                 array = ThuLongLeap;
0196             }
0197             break;
0198         }
0199     }
0200     QString buffer;
0201 
0202     if (!array) { /* Something is terribly wrong! */
0203         buffer = QStringLiteral("??Parsha??");
0204         qCWarning(KORGANIZER_HEBREWPLUGIN_LOG) << "Hebrew Plugin: Was not able to determine the Parsha."
0205                                                << "Please report this as a bug.";
0206         return buffer;
0207     }
0208 
0209     index = array[week];
0210     if (index == XX) { // no Parsha this week.
0211         buffer.clear();
0212         return buffer;
0213     } else if (index < 100) {
0214         buffer = parshiotNames[index];
0215         return buffer;
0216     } else { // Create a double parsha
0217         buffer = parshiotNames[index - 100] + QLatin1Char('-') + parshiotNames[index - 99];
0218         return buffer;
0219     }
0220 }