xref: /webtrees/app/Date/JewishDate.php (revision 4a83f5d742e43c37a641392fe50a3db201bffb30)
1a25f0a04SGreg Roach<?php
2a25f0a04SGreg Roach/**
3a25f0a04SGreg Roach * webtrees: online genealogy
41062a142SGreg Roach * Copyright (C) 2018 webtrees development team
5a25f0a04SGreg Roach * This program is free software: you can redistribute it and/or modify
6a25f0a04SGreg Roach * it under the terms of the GNU General Public License as published by
7a25f0a04SGreg Roach * the Free Software Foundation, either version 3 of the License, or
8a25f0a04SGreg Roach * (at your option) any later version.
9a25f0a04SGreg Roach * This program is distributed in the hope that it will be useful,
10a25f0a04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
11a25f0a04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12a25f0a04SGreg Roach * GNU General Public License for more details.
13a25f0a04SGreg Roach * You should have received a copy of the GNU General Public License
14a25f0a04SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
15a25f0a04SGreg Roach */
16e7f56f2aSGreg Roachdeclare(strict_types=1);
17e7f56f2aSGreg Roach
1876692c8bSGreg Roachnamespace Fisharebest\Webtrees\Date;
19a25f0a04SGreg Roach
20a25f0a04SGreg Roachuse Fisharebest\ExtCalendar\JewishCalendar;
210e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N;
22a25f0a04SGreg Roach
23a25f0a04SGreg Roach/**
2476692c8bSGreg Roach * Definitions for the Jewish calendar
25a25f0a04SGreg Roach */
26*4a83f5d7SGreg Roachclass JewishDate extends AbstractCalendarDate
27c1010edaSGreg Roach{
28*4a83f5d7SGreg Roach    // GEDCOM calendar escape
29*4a83f5d7SGreg Roach    const ESCAPE = '@#DHEBREW@';
30*4a83f5d7SGreg Roach
3152348eb8SGreg Roach    // Convert GEDCOM month names to month numbers
3252348eb8SGreg Roach    const MONTH_ABBREVIATIONS = [
33c1010edaSGreg Roach        ''    => 0,
34c1010edaSGreg Roach        'TSH' => 1,
35c1010edaSGreg Roach        'CSH' => 2,
36c1010edaSGreg Roach        'KSL' => 3,
37c1010edaSGreg Roach        'TVT' => 4,
38c1010edaSGreg Roach        'SHV' => 5,
39c1010edaSGreg Roach        'ADR' => 6,
40c1010edaSGreg Roach        'ADS' => 7,
41c1010edaSGreg Roach        'NSN' => 8,
42c1010edaSGreg Roach        'IYR' => 9,
43c1010edaSGreg Roach        'SVN' => 10,
44c1010edaSGreg Roach        'TMZ' => 11,
45c1010edaSGreg Roach        'AAV' => 12,
46c1010edaSGreg Roach        'ELL' => 13,
47c1010edaSGreg Roach    ];
48a25f0a04SGreg Roach
4976692c8bSGreg Roach    /**
5076692c8bSGreg Roach     * Create a date from either:
5176692c8bSGreg Roach     * a Julian day number
5276692c8bSGreg Roach     * day/month/year strings from a GEDCOM date
5376692c8bSGreg Roach     * another CalendarDate object
5476692c8bSGreg Roach     *
55*4a83f5d7SGreg Roach     * @param array|int|AbstractCalendarDate $date
5676692c8bSGreg Roach     */
57c1010edaSGreg Roach    public function __construct($date)
58c1010edaSGreg Roach    {
5959f2f229SGreg Roach        $this->calendar = new JewishCalendar();
60a25f0a04SGreg Roach        parent::__construct($date);
61a25f0a04SGreg Roach    }
62a25f0a04SGreg Roach
6376692c8bSGreg Roach    /**
6476692c8bSGreg Roach     * Generate the %j format for a date.
6576692c8bSGreg Roach     *
6676692c8bSGreg Roach     * @return string
6776692c8bSGreg Roach     */
68fe11e66dSGreg Roach    protected function formatDay(): string
69c1010edaSGreg Roach    {
7017920f94SGreg Roach        if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
71*4a83f5d7SGreg Roach            return (new JewishCalendar())->numberToHebrewNumerals($this->day, true);
72a25f0a04SGreg Roach        }
73b2ce94c6SRico Sonntag
74b2ce94c6SRico Sonntag        return parent::formatDay();
75a25f0a04SGreg Roach    }
76a25f0a04SGreg Roach
7776692c8bSGreg Roach    /**
7876692c8bSGreg Roach     * Generate the %y format for a date.
7976692c8bSGreg Roach     *
8076692c8bSGreg Roach     * NOTE Short year is NOT a 2-digit year. It is for calendars such as hebrew
8176692c8bSGreg Roach     * which have a 3-digit form of 4-digit years.
8276692c8bSGreg Roach     *
8376692c8bSGreg Roach     * @return string
8476692c8bSGreg Roach     */
85fe11e66dSGreg Roach    protected function formatShortYear(): string
86c1010edaSGreg Roach    {
8717920f94SGreg Roach        if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
88*4a83f5d7SGreg Roach            return (new JewishCalendar())->numberToHebrewNumerals($this->year, false);
89a25f0a04SGreg Roach        }
90b2ce94c6SRico Sonntag
91b2ce94c6SRico Sonntag        return parent::formatLongYear();
92a25f0a04SGreg Roach    }
93a25f0a04SGreg Roach
9476692c8bSGreg Roach    /**
9576692c8bSGreg Roach     * Generate the %Y format for a date.
9676692c8bSGreg Roach     *
9776692c8bSGreg Roach     * @return string
9876692c8bSGreg Roach     */
99fe11e66dSGreg Roach    protected function formatLongYear(): string
100c1010edaSGreg Roach    {
10117920f94SGreg Roach        if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
102*4a83f5d7SGreg Roach            return (new JewishCalendar())->numberToHebrewNumerals($this->year, true);
103a25f0a04SGreg Roach        }
104b2ce94c6SRico Sonntag
105b2ce94c6SRico Sonntag        return parent::formatLongYear();
106a25f0a04SGreg Roach    }
107a25f0a04SGreg Roach
10876692c8bSGreg Roach    /**
10976692c8bSGreg Roach     * Full month name in nominative case.
11076692c8bSGreg Roach     *
11176692c8bSGreg Roach     * @param int  $month_number
11276692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
11376692c8bSGreg Roach     *
11476692c8bSGreg Roach     * @return string
11576692c8bSGreg Roach     */
116220febf9SGreg Roach    protected function monthNameNominativeCase(int $month_number, bool $leap_year): string
117c1010edaSGreg Roach    {
118a25f0a04SGreg Roach        static $translated_month_names;
119a25f0a04SGreg Roach
120a25f0a04SGreg Roach        if ($translated_month_names === null) {
12113abd6f3SGreg Roach            $translated_month_names = [
122a25f0a04SGreg Roach                0  => '',
123bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
124bbb76c12SGreg Roach                1  => I18N::translateContext('NOMINATIVE', 'Tishrei'),
125bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
126bbb76c12SGreg Roach                2  => I18N::translateContext('NOMINATIVE', 'Heshvan'),
127bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
128bbb76c12SGreg Roach                3  => I18N::translateContext('NOMINATIVE', 'Kislev'),
129bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
130bbb76c12SGreg Roach                4  => I18N::translateContext('NOMINATIVE', 'Tevet'),
131bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
132bbb76c12SGreg Roach                5  => I18N::translateContext('NOMINATIVE', 'Shevat'),
133bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
134bbb76c12SGreg Roach                6  => I18N::translateContext('NOMINATIVE', 'Adar I'),
135bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
136bbb76c12SGreg Roach                7  => I18N::translateContext('NOMINATIVE', 'Adar'),
137bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
138bbb76c12SGreg Roach                -7 => I18N::translateContext('NOMINATIVE', 'Adar II'),
139bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
140bbb76c12SGreg Roach                8  => I18N::translateContext('NOMINATIVE', 'Nissan'),
141bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
142bbb76c12SGreg Roach                9  => I18N::translateContext('NOMINATIVE', 'Iyar'),
143bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
144bbb76c12SGreg Roach                10 => I18N::translateContext('NOMINATIVE', 'Sivan'),
145bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
146bbb76c12SGreg Roach                11 => I18N::translateContext('NOMINATIVE', 'Tamuz'),
147bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
148bbb76c12SGreg Roach                12 => I18N::translateContext('NOMINATIVE', 'Av'),
149bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
150bbb76c12SGreg Roach                13 => I18N::translateContext('NOMINATIVE', 'Elul'),
15113abd6f3SGreg Roach            ];
152a25f0a04SGreg Roach        }
153a25f0a04SGreg Roach
154a25f0a04SGreg Roach        if ($month_number === 7 && $leap_year) {
155a25f0a04SGreg Roach            return $translated_month_names[-7];
156a25f0a04SGreg Roach        }
157b2ce94c6SRico Sonntag
158b2ce94c6SRico Sonntag        return $translated_month_names[$month_number];
159a25f0a04SGreg Roach    }
160a25f0a04SGreg Roach
16176692c8bSGreg Roach    /**
16276692c8bSGreg Roach     * Full month name in genitive case.
16376692c8bSGreg Roach     *
16476692c8bSGreg Roach     * @param int  $month_number
16576692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
16676692c8bSGreg Roach     *
16776692c8bSGreg Roach     * @return string
16876692c8bSGreg Roach     */
169fe11e66dSGreg Roach    protected function monthNameGenitiveCase(int $month_number, bool $leap_year): string
170c1010edaSGreg Roach    {
171a25f0a04SGreg Roach        static $translated_month_names;
172a25f0a04SGreg Roach
173a25f0a04SGreg Roach        if ($translated_month_names === null) {
17413abd6f3SGreg Roach            $translated_month_names = [
175a25f0a04SGreg Roach                0  => '',
176bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
177bbb76c12SGreg Roach                1  => I18N::translateContext('GENITIVE', 'Tishrei'),
178bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
179bbb76c12SGreg Roach                2  => I18N::translateContext('GENITIVE', 'Heshvan'),
180bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
181bbb76c12SGreg Roach                3  => I18N::translateContext('GENITIVE', 'Kislev'),
182bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
183bbb76c12SGreg Roach                4  => I18N::translateContext('GENITIVE', 'Tevet'),
184bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
185bbb76c12SGreg Roach                5  => I18N::translateContext('GENITIVE', 'Shevat'),
186bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
187bbb76c12SGreg Roach                6  => I18N::translateContext('GENITIVE', 'Adar I'),
188bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
189bbb76c12SGreg Roach                7  => I18N::translateContext('GENITIVE', 'Adar'),
190bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
191bbb76c12SGreg Roach                -7 => I18N::translateContext('GENITIVE', 'Adar II'),
192bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
193bbb76c12SGreg Roach                8  => I18N::translateContext('GENITIVE', 'Nissan'),
194bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
195bbb76c12SGreg Roach                9  => I18N::translateContext('GENITIVE', 'Iyar'),
196bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
197bbb76c12SGreg Roach                10 => I18N::translateContext('GENITIVE', 'Sivan'),
198bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
199bbb76c12SGreg Roach                11 => I18N::translateContext('GENITIVE', 'Tamuz'),
200bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
201bbb76c12SGreg Roach                12 => I18N::translateContext('GENITIVE', 'Av'),
202bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
203bbb76c12SGreg Roach                13 => I18N::translateContext('GENITIVE', 'Elul'),
20413abd6f3SGreg Roach            ];
205a25f0a04SGreg Roach        }
206a25f0a04SGreg Roach
207a25f0a04SGreg Roach        if ($month_number === 7 && $leap_year) {
208a25f0a04SGreg Roach            return $translated_month_names[-7];
209a25f0a04SGreg Roach        }
210b2ce94c6SRico Sonntag
211b2ce94c6SRico Sonntag        return $translated_month_names[$month_number];
212a25f0a04SGreg Roach    }
213a25f0a04SGreg Roach
21476692c8bSGreg Roach    /**
21576692c8bSGreg Roach     * Full month name in locative case.
21676692c8bSGreg Roach     *
21776692c8bSGreg Roach     * @param int  $month_number
21876692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
21976692c8bSGreg Roach     *
22076692c8bSGreg Roach     * @return string
22176692c8bSGreg Roach     */
222fe11e66dSGreg Roach    protected function monthNameLocativeCase(int $month_number, bool $leap_year): string
223c1010edaSGreg Roach    {
224a25f0a04SGreg Roach        static $translated_month_names;
225a25f0a04SGreg Roach
226a25f0a04SGreg Roach        if ($translated_month_names === null) {
22713abd6f3SGreg Roach            $translated_month_names = [
228a25f0a04SGreg Roach                0  => '',
229bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
230bbb76c12SGreg Roach                1  => I18N::translateContext('LOCATIVE', 'Tishrei'),
231bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
232bbb76c12SGreg Roach                2  => I18N::translateContext('LOCATIVE', 'Heshvan'),
233bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
234bbb76c12SGreg Roach                3  => I18N::translateContext('LOCATIVE', 'Kislev'),
235bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
236bbb76c12SGreg Roach                4  => I18N::translateContext('LOCATIVE', 'Tevet'),
237bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
238bbb76c12SGreg Roach                5  => I18N::translateContext('LOCATIVE', 'Shevat'),
239bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
240bbb76c12SGreg Roach                6  => I18N::translateContext('LOCATIVE', 'Adar I'),
241bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
242bbb76c12SGreg Roach                7  => I18N::translateContext('LOCATIVE', 'Adar'),
243bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
244bbb76c12SGreg Roach                -7 => I18N::translateContext('LOCATIVE', 'Adar II'),
245bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
246bbb76c12SGreg Roach                8  => I18N::translateContext('LOCATIVE', 'Nissan'),
247bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
248bbb76c12SGreg Roach                9  => I18N::translateContext('LOCATIVE', 'Iyar'),
249bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
250bbb76c12SGreg Roach                10 => I18N::translateContext('LOCATIVE', 'Sivan'),
251bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
252bbb76c12SGreg Roach                11 => I18N::translateContext('LOCATIVE', 'Tamuz'),
253bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
254bbb76c12SGreg Roach                12 => I18N::translateContext('LOCATIVE', 'Av'),
255bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
256bbb76c12SGreg Roach                13 => I18N::translateContext('LOCATIVE', 'Elul'),
25713abd6f3SGreg Roach            ];
258a25f0a04SGreg Roach        }
259a25f0a04SGreg Roach
260a25f0a04SGreg Roach        if ($month_number === 7 && $leap_year) {
261a25f0a04SGreg Roach            return $translated_month_names[-7];
262a25f0a04SGreg Roach        }
263b2ce94c6SRico Sonntag
264b2ce94c6SRico Sonntag        return $translated_month_names[$month_number];
265a25f0a04SGreg Roach    }
266a25f0a04SGreg Roach
26776692c8bSGreg Roach    /**
26876692c8bSGreg Roach     * Full month name in instrumental case.
26976692c8bSGreg Roach     *
27076692c8bSGreg Roach     * @param int  $month_number
27176692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
27276692c8bSGreg Roach     *
27376692c8bSGreg Roach     * @return string
27476692c8bSGreg Roach     */
275fe11e66dSGreg Roach    protected function monthNameInstrumentalCase(int $month_number, bool $leap_year): string
276c1010edaSGreg Roach    {
277a25f0a04SGreg Roach        static $translated_month_names;
278a25f0a04SGreg Roach
279a25f0a04SGreg Roach        if ($translated_month_names === null) {
28013abd6f3SGreg Roach            $translated_month_names = [
281a25f0a04SGreg Roach                0  => '',
282bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
283bbb76c12SGreg Roach                1  => I18N::translateContext('INSTRUMENTAL', 'Tishrei'),
284bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
285bbb76c12SGreg Roach                2  => I18N::translateContext('INSTRUMENTAL', 'Heshvan'),
286bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
287bbb76c12SGreg Roach                3  => I18N::translateContext('INSTRUMENTAL', 'Kislev'),
288bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
289bbb76c12SGreg Roach                4  => I18N::translateContext('INSTRUMENTAL', 'Tevet'),
290bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
291bbb76c12SGreg Roach                5  => I18N::translateContext('INSTRUMENTAL', 'Shevat'),
292bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
293bbb76c12SGreg Roach                6  => I18N::translateContext('INSTRUMENTAL', 'Adar I'),
294bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
295bbb76c12SGreg Roach                7  => I18N::translateContext('INSTRUMENTAL', 'Adar'),
296bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
297bbb76c12SGreg Roach                -7 => I18N::translateContext('INSTRUMENTAL', 'Adar II'),
298bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
299bbb76c12SGreg Roach                8  => I18N::translateContext('INSTRUMENTAL', 'Nissan'),
300bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
301bbb76c12SGreg Roach                9  => I18N::translateContext('INSTRUMENTAL', 'Iyar'),
302bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
303bbb76c12SGreg Roach                10 => I18N::translateContext('INSTRUMENTAL', 'Sivan'),
304bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
305bbb76c12SGreg Roach                11 => I18N::translateContext('INSTRUMENTAL', 'Tamuz'),
306bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
307bbb76c12SGreg Roach                12 => I18N::translateContext('INSTRUMENTAL', 'Av'),
308bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
309bbb76c12SGreg Roach                13 => I18N::translateContext('INSTRUMENTAL', 'Elul'),
31013abd6f3SGreg Roach            ];
311a25f0a04SGreg Roach        }
312a25f0a04SGreg Roach
313a25f0a04SGreg Roach        if ($month_number === 7 && $leap_year) {
314a25f0a04SGreg Roach            return $translated_month_names[-7];
315a25f0a04SGreg Roach        }
316b2ce94c6SRico Sonntag
317b2ce94c6SRico Sonntag        return $translated_month_names[$month_number];
318a25f0a04SGreg Roach    }
319a25f0a04SGreg Roach
32076692c8bSGreg Roach    /**
32176692c8bSGreg Roach     * Abbreviated month name
32276692c8bSGreg Roach     *
32376692c8bSGreg Roach     * @param int  $month_number
32476692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
32576692c8bSGreg Roach     *
32676692c8bSGreg Roach     * @return string
32776692c8bSGreg Roach     */
328fe11e66dSGreg Roach    protected function monthNameAbbreviated(int $month_number, bool $leap_year): string
329c1010edaSGreg Roach    {
33040c81a71SGreg Roach        return $this->monthNameNominativeCase($month_number, $leap_year);
331a25f0a04SGreg Roach    }
332a25f0a04SGreg Roach
33376692c8bSGreg Roach    /**
33476692c8bSGreg Roach     * Which months follows this one? Calendars with leap-months should provide their own implementation.
33576692c8bSGreg Roach     *
336e2052359SGreg Roach     * @return int[]
33776692c8bSGreg Roach     */
338fe11e66dSGreg Roach    protected function nextMonth(): array
339c1010edaSGreg Roach    {
340*4a83f5d7SGreg Roach        if ($this->month == 6 && !$this->isLeapYear()) {
341c1010edaSGreg Roach            return [
342*4a83f5d7SGreg Roach                $this->year,
343c1010edaSGreg Roach                8,
344c1010edaSGreg Roach            ];
345b2ce94c6SRico Sonntag        }
346b2ce94c6SRico Sonntag
347c1010edaSGreg Roach        return [
348*4a83f5d7SGreg Roach            $this->year + ($this->month == 13 ? 1 : 0),
349*4a83f5d7SGreg Roach            ($this->month % 13) + 1,
350c1010edaSGreg Roach        ];
351a25f0a04SGreg Roach    }
352a25f0a04SGreg Roach}
353