xref: /webtrees/app/Date/JewishDate.php (revision 40c81a71f02d6f8c393cad5768bd16ca7c5f51b3)
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 */
26c1010edaSGreg Roachclass JewishDate extends CalendarDate
27c1010edaSGreg Roach{
2852348eb8SGreg Roach    // Convert GEDCOM month names to month numbers
2952348eb8SGreg Roach    const MONTH_ABBREVIATIONS = [
30c1010edaSGreg Roach        ''    => 0,
31c1010edaSGreg Roach        'TSH' => 1,
32c1010edaSGreg Roach        'CSH' => 2,
33c1010edaSGreg Roach        'KSL' => 3,
34c1010edaSGreg Roach        'TVT' => 4,
35c1010edaSGreg Roach        'SHV' => 5,
36c1010edaSGreg Roach        'ADR' => 6,
37c1010edaSGreg Roach        'ADS' => 7,
38c1010edaSGreg Roach        'NSN' => 8,
39c1010edaSGreg Roach        'IYR' => 9,
40c1010edaSGreg Roach        'SVN' => 10,
41c1010edaSGreg Roach        'TMZ' => 11,
42c1010edaSGreg Roach        'AAV' => 12,
43c1010edaSGreg Roach        'ELL' => 13,
44c1010edaSGreg Roach    ];
45a25f0a04SGreg Roach
4676692c8bSGreg Roach    /**
4776692c8bSGreg Roach     * Create a date from either:
4876692c8bSGreg Roach     * a Julian day number
4976692c8bSGreg Roach     * day/month/year strings from a GEDCOM date
5076692c8bSGreg Roach     * another CalendarDate object
5176692c8bSGreg Roach     *
5276692c8bSGreg Roach     * @param array|int|CalendarDate $date
5376692c8bSGreg Roach     */
54c1010edaSGreg Roach    public function __construct($date)
55c1010edaSGreg Roach    {
5659f2f229SGreg Roach        $this->calendar = new JewishCalendar();
57a25f0a04SGreg Roach        parent::__construct($date);
58a25f0a04SGreg Roach    }
59a25f0a04SGreg Roach
6076692c8bSGreg Roach    /**
6176692c8bSGreg Roach     * Generate the %j format for a date.
6276692c8bSGreg Roach     *
6376692c8bSGreg Roach     * @return string
6476692c8bSGreg Roach     */
65fe11e66dSGreg Roach    protected function formatDay(): string
66c1010edaSGreg Roach    {
6717920f94SGreg Roach        if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
6859f2f229SGreg Roach            return (new JewishCalendar())->numberToHebrewNumerals($this->d, true);
69a25f0a04SGreg Roach        }
70b2ce94c6SRico Sonntag
71b2ce94c6SRico Sonntag        return parent::formatDay();
72a25f0a04SGreg Roach    }
73a25f0a04SGreg Roach
7476692c8bSGreg Roach    /**
7576692c8bSGreg Roach     * Generate the %y format for a date.
7676692c8bSGreg Roach     *
7776692c8bSGreg Roach     * NOTE Short year is NOT a 2-digit year. It is for calendars such as hebrew
7876692c8bSGreg Roach     * which have a 3-digit form of 4-digit years.
7976692c8bSGreg Roach     *
8076692c8bSGreg Roach     * @return string
8176692c8bSGreg Roach     */
82fe11e66dSGreg Roach    protected function formatShortYear(): string
83c1010edaSGreg Roach    {
8417920f94SGreg Roach        if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
8559f2f229SGreg Roach            return (new JewishCalendar())->numberToHebrewNumerals($this->y, false);
86a25f0a04SGreg Roach        }
87b2ce94c6SRico Sonntag
88b2ce94c6SRico Sonntag        return parent::formatLongYear();
89a25f0a04SGreg Roach    }
90a25f0a04SGreg Roach
9176692c8bSGreg Roach    /**
9276692c8bSGreg Roach     * Generate the %Y format for a date.
9376692c8bSGreg Roach     *
9476692c8bSGreg Roach     * @return string
9576692c8bSGreg Roach     */
96fe11e66dSGreg Roach    protected function formatLongYear(): string
97c1010edaSGreg Roach    {
9817920f94SGreg Roach        if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
9959f2f229SGreg Roach            return (new JewishCalendar())->numberToHebrewNumerals($this->y, true);
100a25f0a04SGreg Roach        }
101b2ce94c6SRico Sonntag
102b2ce94c6SRico Sonntag        return parent::formatLongYear();
103a25f0a04SGreg Roach    }
104a25f0a04SGreg Roach
10576692c8bSGreg Roach    /**
10676692c8bSGreg Roach     * Full month name in nominative case.
10776692c8bSGreg Roach     *
10876692c8bSGreg Roach     * @param int  $month_number
10976692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
11076692c8bSGreg Roach     *
11176692c8bSGreg Roach     * @return string
11276692c8bSGreg Roach     */
113220febf9SGreg Roach    protected function monthNameNominativeCase(int $month_number, bool $leap_year): string
114c1010edaSGreg Roach    {
115a25f0a04SGreg Roach        static $translated_month_names;
116a25f0a04SGreg Roach
117a25f0a04SGreg Roach        if ($translated_month_names === null) {
11813abd6f3SGreg Roach            $translated_month_names = [
119a25f0a04SGreg Roach                0  => '',
120bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
121bbb76c12SGreg Roach                1  => I18N::translateContext('NOMINATIVE', 'Tishrei'),
122bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
123bbb76c12SGreg Roach                2  => I18N::translateContext('NOMINATIVE', 'Heshvan'),
124bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
125bbb76c12SGreg Roach                3  => I18N::translateContext('NOMINATIVE', 'Kislev'),
126bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
127bbb76c12SGreg Roach                4  => I18N::translateContext('NOMINATIVE', 'Tevet'),
128bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
129bbb76c12SGreg Roach                5  => I18N::translateContext('NOMINATIVE', 'Shevat'),
130bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
131bbb76c12SGreg Roach                6  => I18N::translateContext('NOMINATIVE', 'Adar I'),
132bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
133bbb76c12SGreg Roach                7  => I18N::translateContext('NOMINATIVE', 'Adar'),
134bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
135bbb76c12SGreg Roach                -7 => I18N::translateContext('NOMINATIVE', 'Adar II'),
136bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
137bbb76c12SGreg Roach                8  => I18N::translateContext('NOMINATIVE', 'Nissan'),
138bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
139bbb76c12SGreg Roach                9  => I18N::translateContext('NOMINATIVE', 'Iyar'),
140bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
141bbb76c12SGreg Roach                10 => I18N::translateContext('NOMINATIVE', 'Sivan'),
142bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
143bbb76c12SGreg Roach                11 => I18N::translateContext('NOMINATIVE', 'Tamuz'),
144bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
145bbb76c12SGreg Roach                12 => I18N::translateContext('NOMINATIVE', 'Av'),
146bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
147bbb76c12SGreg Roach                13 => I18N::translateContext('NOMINATIVE', 'Elul'),
14813abd6f3SGreg Roach            ];
149a25f0a04SGreg Roach        }
150a25f0a04SGreg Roach
151a25f0a04SGreg Roach        if ($month_number === 7 && $leap_year) {
152a25f0a04SGreg Roach            return $translated_month_names[-7];
153a25f0a04SGreg Roach        }
154b2ce94c6SRico Sonntag
155b2ce94c6SRico Sonntag        return $translated_month_names[$month_number];
156a25f0a04SGreg Roach    }
157a25f0a04SGreg Roach
15876692c8bSGreg Roach    /**
15976692c8bSGreg Roach     * Full month name in genitive case.
16076692c8bSGreg Roach     *
16176692c8bSGreg Roach     * @param int  $month_number
16276692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
16376692c8bSGreg Roach     *
16476692c8bSGreg Roach     * @return string
16576692c8bSGreg Roach     */
166fe11e66dSGreg Roach    protected function monthNameGenitiveCase(int $month_number, bool $leap_year): string
167c1010edaSGreg Roach    {
168a25f0a04SGreg Roach        static $translated_month_names;
169a25f0a04SGreg Roach
170a25f0a04SGreg Roach        if ($translated_month_names === null) {
17113abd6f3SGreg Roach            $translated_month_names = [
172a25f0a04SGreg Roach                0  => '',
173bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
174bbb76c12SGreg Roach                1  => I18N::translateContext('GENITIVE', 'Tishrei'),
175bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
176bbb76c12SGreg Roach                2  => I18N::translateContext('GENITIVE', 'Heshvan'),
177bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
178bbb76c12SGreg Roach                3  => I18N::translateContext('GENITIVE', 'Kislev'),
179bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
180bbb76c12SGreg Roach                4  => I18N::translateContext('GENITIVE', 'Tevet'),
181bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
182bbb76c12SGreg Roach                5  => I18N::translateContext('GENITIVE', 'Shevat'),
183bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
184bbb76c12SGreg Roach                6  => I18N::translateContext('GENITIVE', 'Adar I'),
185bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
186bbb76c12SGreg Roach                7  => I18N::translateContext('GENITIVE', 'Adar'),
187bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
188bbb76c12SGreg Roach                -7 => I18N::translateContext('GENITIVE', 'Adar II'),
189bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
190bbb76c12SGreg Roach                8  => I18N::translateContext('GENITIVE', 'Nissan'),
191bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
192bbb76c12SGreg Roach                9  => I18N::translateContext('GENITIVE', 'Iyar'),
193bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
194bbb76c12SGreg Roach                10 => I18N::translateContext('GENITIVE', 'Sivan'),
195bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
196bbb76c12SGreg Roach                11 => I18N::translateContext('GENITIVE', 'Tamuz'),
197bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
198bbb76c12SGreg Roach                12 => I18N::translateContext('GENITIVE', 'Av'),
199bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
200bbb76c12SGreg Roach                13 => I18N::translateContext('GENITIVE', 'Elul'),
20113abd6f3SGreg Roach            ];
202a25f0a04SGreg Roach        }
203a25f0a04SGreg Roach
204a25f0a04SGreg Roach        if ($month_number === 7 && $leap_year) {
205a25f0a04SGreg Roach            return $translated_month_names[-7];
206a25f0a04SGreg Roach        }
207b2ce94c6SRico Sonntag
208b2ce94c6SRico Sonntag        return $translated_month_names[$month_number];
209a25f0a04SGreg Roach    }
210a25f0a04SGreg Roach
21176692c8bSGreg Roach    /**
21276692c8bSGreg Roach     * Full month name in locative case.
21376692c8bSGreg Roach     *
21476692c8bSGreg Roach     * @param int  $month_number
21576692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
21676692c8bSGreg Roach     *
21776692c8bSGreg Roach     * @return string
21876692c8bSGreg Roach     */
219fe11e66dSGreg Roach    protected function monthNameLocativeCase(int $month_number, bool $leap_year): string
220c1010edaSGreg Roach    {
221a25f0a04SGreg Roach        static $translated_month_names;
222a25f0a04SGreg Roach
223a25f0a04SGreg Roach        if ($translated_month_names === null) {
22413abd6f3SGreg Roach            $translated_month_names = [
225a25f0a04SGreg Roach                0  => '',
226bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
227bbb76c12SGreg Roach                1  => I18N::translateContext('LOCATIVE', 'Tishrei'),
228bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
229bbb76c12SGreg Roach                2  => I18N::translateContext('LOCATIVE', 'Heshvan'),
230bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
231bbb76c12SGreg Roach                3  => I18N::translateContext('LOCATIVE', 'Kislev'),
232bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
233bbb76c12SGreg Roach                4  => I18N::translateContext('LOCATIVE', 'Tevet'),
234bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
235bbb76c12SGreg Roach                5  => I18N::translateContext('LOCATIVE', 'Shevat'),
236bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
237bbb76c12SGreg Roach                6  => I18N::translateContext('LOCATIVE', 'Adar I'),
238bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
239bbb76c12SGreg Roach                7  => I18N::translateContext('LOCATIVE', 'Adar'),
240bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
241bbb76c12SGreg Roach                -7 => I18N::translateContext('LOCATIVE', 'Adar II'),
242bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
243bbb76c12SGreg Roach                8  => I18N::translateContext('LOCATIVE', 'Nissan'),
244bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
245bbb76c12SGreg Roach                9  => I18N::translateContext('LOCATIVE', 'Iyar'),
246bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
247bbb76c12SGreg Roach                10 => I18N::translateContext('LOCATIVE', 'Sivan'),
248bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
249bbb76c12SGreg Roach                11 => I18N::translateContext('LOCATIVE', 'Tamuz'),
250bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
251bbb76c12SGreg Roach                12 => I18N::translateContext('LOCATIVE', 'Av'),
252bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
253bbb76c12SGreg Roach                13 => I18N::translateContext('LOCATIVE', 'Elul'),
25413abd6f3SGreg Roach            ];
255a25f0a04SGreg Roach        }
256a25f0a04SGreg Roach
257a25f0a04SGreg Roach        if ($month_number === 7 && $leap_year) {
258a25f0a04SGreg Roach            return $translated_month_names[-7];
259a25f0a04SGreg Roach        }
260b2ce94c6SRico Sonntag
261b2ce94c6SRico Sonntag        return $translated_month_names[$month_number];
262a25f0a04SGreg Roach    }
263a25f0a04SGreg Roach
26476692c8bSGreg Roach    /**
26576692c8bSGreg Roach     * Full month name in instrumental case.
26676692c8bSGreg Roach     *
26776692c8bSGreg Roach     * @param int  $month_number
26876692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
26976692c8bSGreg Roach     *
27076692c8bSGreg Roach     * @return string
27176692c8bSGreg Roach     */
272fe11e66dSGreg Roach    protected function monthNameInstrumentalCase(int $month_number, bool $leap_year): string
273c1010edaSGreg Roach    {
274a25f0a04SGreg Roach        static $translated_month_names;
275a25f0a04SGreg Roach
276a25f0a04SGreg Roach        if ($translated_month_names === null) {
27713abd6f3SGreg Roach            $translated_month_names = [
278a25f0a04SGreg Roach                0  => '',
279bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
280bbb76c12SGreg Roach                1  => I18N::translateContext('INSTRUMENTAL', 'Tishrei'),
281bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
282bbb76c12SGreg Roach                2  => I18N::translateContext('INSTRUMENTAL', 'Heshvan'),
283bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
284bbb76c12SGreg Roach                3  => I18N::translateContext('INSTRUMENTAL', 'Kislev'),
285bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
286bbb76c12SGreg Roach                4  => I18N::translateContext('INSTRUMENTAL', 'Tevet'),
287bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
288bbb76c12SGreg Roach                5  => I18N::translateContext('INSTRUMENTAL', 'Shevat'),
289bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
290bbb76c12SGreg Roach                6  => I18N::translateContext('INSTRUMENTAL', 'Adar I'),
291bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
292bbb76c12SGreg Roach                7  => I18N::translateContext('INSTRUMENTAL', 'Adar'),
293bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
294bbb76c12SGreg Roach                -7 => I18N::translateContext('INSTRUMENTAL', 'Adar II'),
295bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
296bbb76c12SGreg Roach                8  => I18N::translateContext('INSTRUMENTAL', 'Nissan'),
297bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
298bbb76c12SGreg Roach                9  => I18N::translateContext('INSTRUMENTAL', 'Iyar'),
299bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
300bbb76c12SGreg Roach                10 => I18N::translateContext('INSTRUMENTAL', 'Sivan'),
301bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
302bbb76c12SGreg Roach                11 => I18N::translateContext('INSTRUMENTAL', 'Tamuz'),
303bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
304bbb76c12SGreg Roach                12 => I18N::translateContext('INSTRUMENTAL', 'Av'),
305bbb76c12SGreg Roach                /* I18N: a month in the Jewish calendar */
306bbb76c12SGreg Roach                13 => I18N::translateContext('INSTRUMENTAL', 'Elul'),
30713abd6f3SGreg Roach            ];
308a25f0a04SGreg Roach        }
309a25f0a04SGreg Roach
310a25f0a04SGreg Roach        if ($month_number === 7 && $leap_year) {
311a25f0a04SGreg Roach            return $translated_month_names[-7];
312a25f0a04SGreg Roach        }
313b2ce94c6SRico Sonntag
314b2ce94c6SRico Sonntag        return $translated_month_names[$month_number];
315a25f0a04SGreg Roach    }
316a25f0a04SGreg Roach
31776692c8bSGreg Roach    /**
31876692c8bSGreg Roach     * Abbreviated month name
31976692c8bSGreg Roach     *
32076692c8bSGreg Roach     * @param int  $month_number
32176692c8bSGreg Roach     * @param bool $leap_year Some calendars use leap months
32276692c8bSGreg Roach     *
32376692c8bSGreg Roach     * @return string
32476692c8bSGreg Roach     */
325fe11e66dSGreg Roach    protected function monthNameAbbreviated(int $month_number, bool $leap_year): string
326c1010edaSGreg Roach    {
327*40c81a71SGreg Roach        return $this->monthNameNominativeCase($month_number, $leap_year);
328a25f0a04SGreg Roach    }
329a25f0a04SGreg Roach
33076692c8bSGreg Roach    /**
33176692c8bSGreg Roach     * Which months follows this one? Calendars with leap-months should provide their own implementation.
33276692c8bSGreg Roach     *
333e2052359SGreg Roach     * @return int[]
33476692c8bSGreg Roach     */
335fe11e66dSGreg Roach    protected function nextMonth(): array
336c1010edaSGreg Roach    {
337a25f0a04SGreg Roach        if ($this->m == 6 && !$this->isLeapYear()) {
338c1010edaSGreg Roach            return [
339c1010edaSGreg Roach                $this->y,
340c1010edaSGreg Roach                8,
341c1010edaSGreg Roach            ];
342b2ce94c6SRico Sonntag        }
343b2ce94c6SRico Sonntag
344c1010edaSGreg Roach        return [
345c1010edaSGreg Roach            $this->y + ($this->m == 13 ? 1 : 0),
346c1010edaSGreg Roach            ($this->m % 13) + 1,
347c1010edaSGreg Roach        ];
348a25f0a04SGreg Roach    }
349a25f0a04SGreg Roach}
350