xref: /webtrees/app/Date/JewishDate.php (revision 46bb661f32cdac2ea7c60006b34b13e316578b11)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2018 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16namespace Fisharebest\Webtrees\Date;
17
18use Fisharebest\ExtCalendar\JewishCalendar;
19use Fisharebest\Webtrees\I18N;
20
21/**
22 * Definitions for the Jewish calendar
23 */
24class JewishDate extends CalendarDate {
25	/** @var int[] Convert GEDCOM month names to month numbers  */
26	public static $MONTH_ABBREV = ['' => 0, 'TSH' => 1, 'CSH' => 2, 'KSL' => 3, 'TVT' => 4, 'SHV' => 5, 'ADR' => 6, 'ADS' => 7, 'NSN' => 8, 'IYR' => 9, 'SVN' => 10, 'TMZ' => 11, 'AAV' => 12, 'ELL' => 13];
27
28	/**
29	 * Create a date from either:
30	 * a Julian day number
31	 * day/month/year strings from a GEDCOM date
32	 * another CalendarDate object
33	 *
34	 * @param array|int|CalendarDate $date
35	 */
36	public function __construct($date) {
37		$this->calendar = new JewishCalendar;
38		parent::__construct($date);
39	}
40
41	/**
42	 * Generate the %j format for a date.
43	 *
44	 * @return string
45	 */
46	protected function formatDay() {
47		if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
48			return (new JewishCalendar)->numberToHebrewNumerals($this->d, true);
49		} else {
50			return $this->d;
51		}
52	}
53
54	/**
55	 * Generate the %y format for a date.
56	 *
57	 * NOTE Short year is NOT a 2-digit year. It is for calendars such as hebrew
58	 * which have a 3-digit form of 4-digit years.
59	 *
60	 * @return string
61	 */
62	protected function formatShortYear() {
63		if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
64			return (new JewishCalendar)->numberToHebrewNumerals($this->y, false);
65		} else {
66			return $this->y;
67		}
68	}
69
70	/**
71	 * Generate the %Y format for a date.
72	 *
73	 * @return string
74	 */
75	protected function formatLongYear() {
76		if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') {
77			return (new JewishCalendar)->numberToHebrewNumerals($this->y, true);
78		} else {
79			return $this->y;
80		}
81	}
82
83	/**
84	 * Full month name in nominative case.
85	 *
86	 * @param int  $month_number
87	 * @param bool $leap_year    Some calendars use leap months
88	 *
89	 * @return string
90	 */
91	public static function monthNameNominativeCase($month_number, $leap_year) {
92		static $translated_month_names;
93
94		if ($translated_month_names === null) {
95			$translated_month_names = [
96				0  => '',
97				1  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tishrei'),
98				2  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Heshvan'),
99				3  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Kislev'),
100				4  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tevet'),
101				5  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Shevat'),
102				6  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar I'),
103				7  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar'),
104				-7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar II'),
105				8  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Nissan'),
106				9  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Iyar'),
107				10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Sivan'),
108				11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tamuz'),
109				12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Av'),
110				13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Elul'),
111			];
112		}
113
114		if ($month_number === 7 && $leap_year) {
115			return $translated_month_names[-7];
116		} else {
117			return $translated_month_names[$month_number];
118		}
119	}
120
121	/**
122	 * Full month name in genitive case.
123	 *
124	 * @param int  $month_number
125	 * @param bool $leap_year    Some calendars use leap months
126	 *
127	 * @return string
128	 */
129	protected function monthNameGenitiveCase($month_number, $leap_year) {
130		static $translated_month_names;
131
132		if ($translated_month_names === null) {
133			$translated_month_names = [
134				0  => '',
135				1  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tishrei'),
136				2  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Heshvan'),
137				3  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Kislev'),
138				4  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tevet'),
139				5  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Shevat'),
140				6  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar I'),
141				7  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar'),
142				-7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar II'),
143				8  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Nissan'),
144				9  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Iyar'),
145				10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Sivan'),
146				11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tamuz'),
147				12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Av'),
148				13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Elul'),
149			];
150		}
151
152		if ($month_number === 7 && $leap_year) {
153			return $translated_month_names[-7];
154		} else {
155			return $translated_month_names[$month_number];
156		}
157	}
158
159	/**
160	 * Full month name in locative case.
161	 *
162	 * @param int  $month_number
163	 * @param bool $leap_year    Some calendars use leap months
164	 *
165	 * @return string
166	 */
167	protected function monthNameLocativeCase($month_number, $leap_year) {
168		static $translated_month_names;
169
170		if ($translated_month_names === null) {
171			$translated_month_names = [
172				0  => '',
173				1  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tishrei'),
174				2  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Heshvan'),
175				3  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Kislev'),
176				4  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tevet'),
177				5  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Shevat'),
178				6  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar I'),
179				7  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar'),
180				-7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar II'),
181				8  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Nissan'),
182				9  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Iyar'),
183				10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Sivan'),
184				11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tamuz'),
185				12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Av'),
186				13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Elul'),
187			];
188		}
189
190		if ($month_number === 7 && $leap_year) {
191			return $translated_month_names[-7];
192		} else {
193			return $translated_month_names[$month_number];
194		}
195	}
196
197	/**
198	 * Full month name in instrumental case.
199	 *
200	 * @param int  $month_number
201	 * @param bool $leap_year    Some calendars use leap months
202	 *
203	 * @return string
204	 */
205	protected function monthNameInstrumentalCase($month_number, $leap_year) {
206		static $translated_month_names;
207
208		if ($translated_month_names === null) {
209			$translated_month_names = [
210				0  => '',
211				1  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tishrei'),
212				2  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Heshvan'),
213				3  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Kislev'),
214				4  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tevet'),
215				5  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Shevat'),
216				6  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar I'),
217				7  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar'),
218				-7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar II'),
219				8  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Nissan'),
220				9  => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Iyar'),
221				10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Sivan'),
222				11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tamuz'),
223				12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Av'),
224				13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Elul'),
225			];
226		}
227
228		if ($month_number === 7 && $leap_year) {
229			return $translated_month_names[-7];
230		} else {
231			return $translated_month_names[$month_number];
232		}
233	}
234
235	/**
236	 * Abbreviated month name
237	 *
238	 * @param int  $month_number
239	 * @param bool $leap_year    Some calendars use leap months
240	 *
241	 * @return string
242	 */
243	protected function monthNameAbbreviated($month_number, $leap_year) {
244		return self::monthNameNominativeCase($month_number, $leap_year);
245	}
246
247	/**
248	 * Which months follows this one? Calendars with leap-months should provide their own implementation.
249	 *
250	 * @return int[]
251	 */
252	protected function nextMonth() {
253		if ($this->m == 6 && !$this->isLeapYear()) {
254			return [$this->y, 8];
255		} else {
256			return [$this->y + ($this->m == 13 ? 1 : 0), ($this->m % 13) + 1];
257		}
258	}
259}
260