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 "parsha.h"
17 #include "korganizer_hebrew_debug.h"
18 #include <KLocalizedString>
19 
findParshaName(int dayNumber,int kvia,bool isLeapYear,bool useIsraelSettings)20 QString Parsha::findParshaName(int dayNumber, int kvia, bool isLeapYear, bool useIsraelSettings)
21 {
22     // The names of the Parshiot.
23     static QStringList parshiotNames = QStringList();
24     parshiotNames << i18nc(
25         "These are weekly readings and do not have translations. "
26         "They may have different spellings in your language; "
27         "otherwise, just translate the sound to your characters",
28         "Bereshit")
29                   << i18n("Noach") << i18n("Lech L'cha") << i18n("Vayera") << i18n("Chaye Sarah") << i18n("Toldot") << i18n("Vayetze") << i18n("Vayishlach")
30                   << i18n("Vayeshev") << i18n("Miketz") << i18n("Vayigash") << i18n("Vayechi") << i18n("Shemot") << i18n("Vaera") << i18n("Bo")
31                   << i18n("Beshalach") << i18n("Yitro") << i18n("Mishpatim") << i18n("Terumah") << i18n("Tetzaveh") << i18n("Ki Tisa") << i18n("Vayakhel")
32                   << i18n("Pekudei") << i18n("Vayikra") << i18n("Tzav") << i18n("Shemini") << i18n("Tazria") << i18n("Metzora") << i18n("Acharei Mot")
33                   << i18n("Kedoshim") << i18n("Emor") << i18n("Behar") << i18n("Bechukotai") << i18n("Bemidbar") << i18n("Naso") << i18n("Behaalotcha")
34                   << i18n("Shelach") << i18n("Korach") << i18n("Chukat") << i18n("Balak") << i18n("Pinchas") << i18n("Matot") << i18n("Masei")
35                   << i18n("Devarim") << i18n("Vaetchanan") << i18n("Ekev") << i18n("Reeh") << i18n("Shoftim") << i18n("Ki Tetze") << i18n("Ki Tavo")
36                   << i18n("Nitzavim") << i18n("Vayelech") << i18n("Haazinu");
37 
38     /*
39       Tables for each of the year types. XX indicates that it is a Holiday, and a
40       special parsha is read that week. For some year types among the 14, Israel
41       is different from the diaspora.
42 
43       The names indicate the day of the week on which Rosh Hashanah fell, whether
44       it is a short/normal/long year (kvia=0,1,2), and whether it is a leap year.
45       As said earlier, some year types also have an _Israel version.
46 
47       The numbers are indices in the list above for a given week.
48       Numbers > 100 indicate a double parsha, e.g. 150 means read both table
49       entries 150 - 100 = 50 and 150 - 99 = 51.
50 
51       These tables were stolen (with some massaging) from the Gnu code.
52     */
53 
54     static const quint8 XX = 255;
55 
56     /* Non-leap years */
57     static const quint8 SatShort[] = {
58         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,
59         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,
60     };
61     static const quint8 SatLong[] = {
62         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,
63         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,
64     };
65 
66     static const quint8 MonShort[] = {
67         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,
68         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,
69     };
70     static const quint8 MonLong[] = /* split */
71         {
72             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,
73             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,
74         };
75 #define MonLong_Israel MonShort
76 
77 #define TueNormal MonLong
78 #define TueNormal_Israel MonShort
79 
80     static const quint8 ThuNormal[] = {
81         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,
82         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,
83     };
84     static const quint8 ThuNormal_Israel[] = {
85         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,
86         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,
87     };
88     static const quint8 ThuLong[] = {
89         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,
90         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,
91     };
92 
93     /* Leap years */
94     static const quint8 SatShortLeap[] = {
95         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,
96         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,
97     };
98     static const quint8 SatLongLeap[] = {
99         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,
100         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,
101     };
102 #define SatLongLeap_Israel SatShortLeap
103 
104     static const quint8 MonShortLeap[] = {
105         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,
106         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,
107     };
108     static const quint8 MonShortLeap_Israel[] = {
109         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,
110         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,
111     };
112     static const quint8 MonLongLeap[] = {
113         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,
114         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,
115     };
116     static const quint8 MonLongLeap_Israel[] = {
117         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,
118         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,
119     };
120 
121 #define TueNormalLeap MonLongLeap
122 #define TueNormalLeap_Israel MonLongLeap_Israel
123 
124     static const quint8 ThuShortLeap[] = {
125         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,
126         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,
127     };
128     static const quint8 ThuLongLeap[] = {
129         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,
130         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,
131     };
132 
133     /* Make the calculations */
134     int week = dayNumber / 7; // week of the year
135     const quint8 *array = nullptr;
136     int index;
137 
138     /* Get the appropriate array by exhaustive search into the 14 year types.
139        Since we know it's a Shabbat, we can find out what day Rosh Hashanah was on
140        by looking at dayNumber % 7. */
141     if (!isLeapYear) {
142         switch (dayNumber % 7) {
143         case 1: /* Rosh Hashanah was on a Saturday */
144             if (kvia == 0) {
145                 array = SatShort;
146             } else if (kvia == 2) {
147                 array = SatLong;
148             }
149             break;
150         case 6: /* Rosh Hashanah was on a Monday */
151             if (kvia == 0) {
152                 array = MonShort;
153             } else if (kvia == 2) {
154                 array = useIsraelSettings ? MonLong_Israel : MonLong;
155             }
156             break;
157         case 5: /* Rosh Hashanah was on a Tuesday */
158             if (kvia == 1) {
159                 array = useIsraelSettings ? TueNormal_Israel : TueNormal;
160             }
161             break;
162         case 3: /* Rosh Hashanah was on a Thursday */
163             if (kvia == 1) {
164                 array = useIsraelSettings ? ThuNormal_Israel : ThuNormal;
165             } else if (kvia == 2) {
166                 array = ThuLong;
167             }
168             break;
169         }
170     } else { /* leap year */
171         switch (dayNumber % 7) {
172         case 1: /* Rosh Hashanah was on a Sat */
173             if (kvia == 0) {
174                 array = SatShortLeap;
175             } else if (kvia == 2) {
176                 array = useIsraelSettings ? SatLongLeap_Israel : SatLongLeap;
177             }
178             break;
179         case 6: /* Rosh Hashanah was on a Monday */
180             if (kvia == 0) {
181                 array = useIsraelSettings ? MonShortLeap_Israel : MonShortLeap;
182             } else if (kvia == 2) {
183                 array = useIsraelSettings ? MonLongLeap_Israel : MonLongLeap;
184             }
185             break;
186         case 5: /* Rosh Hashanah was on a Tuesday */
187             if (kvia == 1) {
188                 array = useIsraelSettings ? TueNormalLeap_Israel : TueNormalLeap;
189             }
190             break;
191         case 3: /* Rosh Hashanah was on a Thursday */
192             if (kvia == 0) {
193                 array = ThuShortLeap;
194             } else if (kvia == 2) {
195                 array = ThuLongLeap;
196             }
197             break;
198         }
199     }
200     QString buffer;
201 
202     if (!array) { /* Something is terribly wrong! */
203         buffer = QStringLiteral("??Parsha??");
204         qCWarning(KORGANIZER_HEBREWPLUGIN_LOG) << "Hebrew Plugin: Was not able to determine the Parsha."
205                                                << "Please report this as a bug.";
206         return buffer;
207     }
208 
209     index = array[week];
210     if (index == XX) { // no Parsha this week.
211         buffer.clear();
212         return buffer;
213     } else if (index < 100) {
214         buffer = parshiotNames[index];
215         return buffer;
216     } else { // Create a double parsha
217         buffer = parshiotNames[index - 100] + QLatin1Char('-') + parshiotNames[index - 99];
218         return buffer;
219     }
220 }
221