xref: /webtrees/app/Date/HijriDate.php (revision e873f434551745f888937263ff89e80db3b0f785)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2023 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Date;
21
22use Fisharebest\ExtCalendar\ArabicCalendar;
23use Fisharebest\Webtrees\I18N;
24
25/**
26 * Definitions for Hijri dates.
27 *
28 * Note that these are "theoretical" dates.
29 * "True" dates are based on local lunar observations, and can be a +/- one day.
30 */
31class HijriDate extends AbstractCalendarDate
32{
33    // GEDCOM calendar escape
34    public const string ESCAPE = '@#DHIJRI@';
35
36    // Convert GEDCOM month names to month numbers
37    protected const array MONTH_TO_NUMBER = [
38        'MUHAR' => 1,
39        'SAFAR' => 2,
40        'RABIA' => 3,
41        'RABIT' => 4,
42        'JUMAA' => 5,
43        'JUMAT' => 6,
44        'RAJAB' => 7,
45        'SHAAB' => 8,
46        'RAMAD' => 9,
47        'SHAWW' => 10,
48        'DHUAQ' => 11,
49        'DHUAH' => 12,
50    ];
51
52    protected const array NUMBER_TO_MONTH = [
53        1  => 'MUHAR',
54        2  => 'SAFAR',
55        3  => 'RABIA',
56        4  => 'RABIT',
57        5  => 'JUMAA',
58        6  => 'JUMAT',
59        7  => 'RAJAB',
60        8  => 'SHAAB',
61        9  => 'RAMAD',
62        10 => 'SHAWW',
63        11 => 'DHUAQ',
64        12 => 'DHUAH',
65    ];
66
67    /**
68     * Create a date from either:
69     * a Julian day number
70     * day/month/year strings from a GEDCOM date
71     * another CalendarDate object
72     *
73     * @param array<string>|int|AbstractCalendarDate $date
74     */
75    public function __construct($date)
76    {
77        $this->calendar = new ArabicCalendar();
78        parent::__construct($date);
79    }
80
81    /**
82     * Full month name in nominative case.
83     *
84     * @param int  $month
85     * @param bool $leap_year Some calendars use leap months
86     *
87     * @return string
88     */
89    protected function monthNameNominativeCase(int $month, bool $leap_year): string
90    {
91        static $translated_month_names;
92
93        if ($translated_month_names === null) {
94            $translated_month_names = [
95                0  => '',
96                /* I18N: https://en.wikipedia.org/wiki/Muharram */
97                1  => I18N::translateContext('NOMINATIVE', 'Muharram'),
98                /* I18N: https://en.wikipedia.org/wiki/Safar */
99                2  => I18N::translateContext('NOMINATIVE', 'Safar'),
100                /* I18N: https://en.wikipedia.org/wiki/Rabi%27_al-awwal */
101                3  => I18N::translateContext('NOMINATIVE', 'Rabi’ al-awwal'),
102                /* I18N: https://en.wikipedia.org/wiki/Rabi%27_al-thani */
103                4  => I18N::translateContext('NOMINATIVE', 'Rabi’ al-thani'),
104                /* I18N: https://en.wikipedia.org/wiki/Jumada_al-awwal */
105                5  => I18N::translateContext('NOMINATIVE', 'Jumada al-awwal'),
106                /* I18N: https://en.wikipedia.org/wiki/Jumada_al-thani */
107                6  => I18N::translateContext('NOMINATIVE', 'Jumada al-thani'),
108                /* I18N: https://en.wikipedia.org/wiki/Rajab */
109                7  => I18N::translateContext('NOMINATIVE', 'Rajab'),
110                /* I18N: https://en.wikipedia.org/wiki/Sha%27aban */
111                8  => I18N::translateContext('NOMINATIVE', 'Sha’aban'),
112                /* I18N: https://en.wikipedia.org/wiki/Ramadan_%28calendar_month%29 */
113                9  => I18N::translateContext('NOMINATIVE', 'Ramadan'),
114                /* I18N: https://en.wikipedia.org/wiki/Shawwal */
115                10 => I18N::translateContext('NOMINATIVE', 'Shawwal'),
116                /* I18N: https://en.wikipedia.org/wiki/Dhu_al-Qi%27dah */
117                11 => I18N::translateContext('NOMINATIVE', 'Dhu al-Qi’dah'),
118                /* I18N: https://en.wikipedia.org/wiki/Dhu_al-Hijjah */
119                12 => I18N::translateContext('NOMINATIVE', 'Dhu al-Hijjah'),
120            ];
121        }
122
123        return $translated_month_names[$month];
124    }
125
126    /**
127     * Full month name in genitive case.
128     *
129     * @param int  $month
130     * @param bool $leap_year Some calendars use leap months
131     *
132     * @return string
133     */
134    protected function monthNameGenitiveCase(int $month, bool $leap_year): string
135    {
136        static $translated_month_names;
137
138        if ($translated_month_names === null) {
139            $translated_month_names = [
140                0  => '',
141                /* I18N: https://en.wikipedia.org/wiki/Muharram */
142                1  => I18N::translateContext('GENITIVE', 'Muharram'),
143                /* I18N: https://en.wikipedia.org/wiki/Safar */
144                2  => I18N::translateContext('GENITIVE', 'Safar'),
145                /* I18N: https://en.wikipedia.org/wiki/Rabi%27_al-awwal */
146                3  => I18N::translateContext('GENITIVE', 'Rabi’ al-awwal'),
147                /* I18N: https://en.wikipedia.org/wiki/Rabi%27_al-thani */
148                4  => I18N::translateContext('GENITIVE', 'Rabi’ al-thani'),
149                /* I18N: https://en.wikipedia.org/wiki/Jumada_al-awwal */
150                5  => I18N::translateContext('GENITIVE', 'Jumada al-awwal'),
151                /* I18N: https://en.wikipedia.org/wiki/Jumada_al-thani */
152                6  => I18N::translateContext('GENITIVE', 'Jumada al-thani'),
153                /* I18N: https://en.wikipedia.org/wiki/Rajab */
154                7  => I18N::translateContext('GENITIVE', 'Rajab'),
155                /* I18N: https://en.wikipedia.org/wiki/Sha%27aban */
156                8  => I18N::translateContext('GENITIVE', 'Sha’aban'),
157                /* I18N: https://en.wikipedia.org/wiki/Ramadan_%28calendar_month%29 */
158                9  => I18N::translateContext('GENITIVE', 'Ramadan'),
159                /* I18N: https://en.wikipedia.org/wiki/Shawwal */
160                10 => I18N::translateContext('GENITIVE', 'Shawwal'),
161                /* I18N: https://en.wikipedia.org/wiki/Dhu_al-Qi%27dah */
162                11 => I18N::translateContext('GENITIVE', 'Dhu al-Qi’dah'),
163                /* I18N: https://en.wikipedia.org/wiki/Dhu_al-Hijjah */
164                12 => I18N::translateContext('GENITIVE', 'Dhu al-Hijjah'),
165            ];
166        }
167
168        return $translated_month_names[$month];
169    }
170
171    /**
172     * Full month name in locative case.
173     *
174     * @param int  $month
175     * @param bool $leap_year Some calendars use leap months
176     *
177     * @return string
178     */
179    protected function monthNameLocativeCase(int $month, bool $leap_year): string
180    {
181        static $translated_month_names;
182
183        if ($translated_month_names === null) {
184            $translated_month_names = [
185                0  => '',
186                /* I18N: https://en.wikipedia.org/wiki/Muharram */
187                1  => I18N::translateContext('LOCATIVE', 'Muharram'),
188                /* I18N: https://en.wikipedia.org/wiki/Safar */
189                2  => I18N::translateContext('LOCATIVE', 'Safar'),
190                /* I18N: https://en.wikipedia.org/wiki/Rabi%27_al-awwal */
191                3  => I18N::translateContext('LOCATIVE', 'Rabi’ al-awwal'),
192                /* I18N: https://en.wikipedia.org/wiki/Rabi%27_al-thani */
193                4  => I18N::translateContext('LOCATIVE', 'Rabi’ al-thani'),
194                /* I18N: https://en.wikipedia.org/wiki/Jumada_al-awwal */
195                5  => I18N::translateContext('LOCATIVE', 'Jumada al-awwal'),
196                /* I18N: https://en.wikipedia.org/wiki/Jumada_al-thani */
197                6  => I18N::translateContext('LOCATIVE', 'Jumada al-thani'),
198                /* I18N: https://en.wikipedia.org/wiki/Rajab */
199                7  => I18N::translateContext('LOCATIVE', 'Rajab'),
200                /* I18N: https://en.wikipedia.org/wiki/Sha%27aban */
201                8  => I18N::translateContext('LOCATIVE', 'Sha’aban'),
202                /* I18N: https://en.wikipedia.org/wiki/Ramadan_%28calendar_month%29 */
203                9  => I18N::translateContext('LOCATIVE', 'Ramadan'),
204                /* I18N: https://en.wikipedia.org/wiki/Shawwal */
205                10 => I18N::translateContext('LOCATIVE', 'Shawwal'),
206                /* I18N: https://en.wikipedia.org/wiki/Dhu_al-Qi%27dah */
207                11 => I18N::translateContext('LOCATIVE', 'Dhu al-Qi’dah'),
208                /* I18N: https://en.wikipedia.org/wiki/Dhu_al-Hijjah */
209                12 => I18N::translateContext('LOCATIVE', 'Dhu al-Hijjah'),
210            ];
211        }
212
213        return $translated_month_names[$month];
214    }
215
216    /**
217     * Full month name in instrumental case.
218     *
219     * @param int  $month
220     * @param bool $leap_year Some calendars use leap months
221     *
222     * @return string
223     */
224    protected function monthNameInstrumentalCase(int $month, bool $leap_year): string
225    {
226        static $translated_month_names;
227
228        if ($translated_month_names === null) {
229            $translated_month_names = [
230                0  => '',
231                /* I18N: https://en.wikipedia.org/wiki/Muharram */
232                1  => I18N::translateContext('INSTRUMENTAL', 'Muharram'),
233                /* I18N: https://en.wikipedia.org/wiki/Safar */
234                2  => I18N::translateContext('INSTRUMENTAL', 'Safar'),
235                /* I18N: https://en.wikipedia.org/wiki/Rabi%27_al-awwal */
236                3  => I18N::translateContext('INSTRUMENTAL', 'Rabi’ al-awwal'),
237                /* I18N: https://en.wikipedia.org/wiki/Rabi%27_al-thani */
238                4  => I18N::translateContext('INSTRUMENTAL', 'Rabi’ al-thani'),
239                /* I18N: https://en.wikipedia.org/wiki/Jumada_al-awwal */
240                5  => I18N::translateContext('INSTRUMENTAL', 'Jumada al-awwal'),
241                /* I18N: https://en.wikipedia.org/wiki/Jumada_al-thani */
242                6  => I18N::translateContext('INSTRUMENTAL', 'Jumada al-thani'),
243                /* I18N: https://en.wikipedia.org/wiki/Rajab */
244                7  => I18N::translateContext('INSTRUMENTAL', 'Rajab'),
245                /* I18N: https://en.wikipedia.org/wiki/Sha%27aban */
246                8  => I18N::translateContext('INSTRUMENTAL', 'Sha’aban'),
247                /* I18N: https://en.wikipedia.org/wiki/Ramadan_%28calendar_month%29 */
248                9  => I18N::translateContext('INSTRUMENTAL', 'Ramadan'),
249                /* I18N: https://en.wikipedia.org/wiki/Shawwal */
250                10 => I18N::translateContext('INSTRUMENTAL', 'Shawwal'),
251                /* I18N: https://en.wikipedia.org/wiki/Dhu_al-Qi%27dah */
252                11 => I18N::translateContext('INSTRUMENTAL', 'Dhu al-Qi’dah'),
253                /* I18N: https://en.wikipedia.org/wiki/Dhu_al-Hijjah */
254                12 => I18N::translateContext('INSTRUMENTAL', 'Dhu al-Hijjah'),
255            ];
256        }
257
258        return $translated_month_names[$month];
259    }
260
261    /**
262     * Abbreviated month name
263     *
264     * @param int  $month
265     * @param bool $leap_year Some calendars use leap months
266     *
267     * @return string
268     */
269    protected function monthNameAbbreviated(int $month, bool $leap_year): string
270    {
271        return $this->monthNameNominativeCase($month, $leap_year);
272    }
273}
274