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{ 26 /** @var int[] Convert GEDCOM month names to month numbers */ 27 public static $MONTH_ABBREV = [ 28 '' => 0, 29 'TSH' => 1, 30 'CSH' => 2, 31 'KSL' => 3, 32 'TVT' => 4, 33 'SHV' => 5, 34 'ADR' => 6, 35 'ADS' => 7, 36 'NSN' => 8, 37 'IYR' => 9, 38 'SVN' => 10, 39 'TMZ' => 11, 40 'AAV' => 12, 41 'ELL' => 13, 42 ]; 43 44 /** 45 * Create a date from either: 46 * a Julian day number 47 * day/month/year strings from a GEDCOM date 48 * another CalendarDate object 49 * 50 * @param array|int|CalendarDate $date 51 */ 52 public function __construct($date) 53 { 54 $this->calendar = new JewishCalendar; 55 parent::__construct($date); 56 } 57 58 /** 59 * Generate the %j format for a date. 60 * 61 * @return string 62 */ 63 protected function formatDay() 64 { 65 if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') { 66 return (new JewishCalendar)->numberToHebrewNumerals($this->d, true); 67 } else { 68 return $this->d; 69 } 70 } 71 72 /** 73 * Generate the %y format for a date. 74 * 75 * NOTE Short year is NOT a 2-digit year. It is for calendars such as hebrew 76 * which have a 3-digit form of 4-digit years. 77 * 78 * @return string 79 */ 80 protected function formatShortYear() 81 { 82 if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') { 83 return (new JewishCalendar)->numberToHebrewNumerals($this->y, false); 84 } else { 85 return $this->y; 86 } 87 } 88 89 /** 90 * Generate the %Y format for a date. 91 * 92 * @return string 93 */ 94 protected function formatLongYear() 95 { 96 if (WT_LOCALE === 'he' || WT_LOCALE === 'yi') { 97 return (new JewishCalendar)->numberToHebrewNumerals($this->y, true); 98 } else { 99 return $this->y; 100 } 101 } 102 103 /** 104 * Full month name in nominative case. 105 * 106 * @param int $month_number 107 * @param bool $leap_year Some calendars use leap months 108 * 109 * @return string 110 */ 111 public static function monthNameNominativeCase($month_number, $leap_year) 112 { 113 static $translated_month_names; 114 115 if ($translated_month_names === null) { 116 $translated_month_names = [ 117 0 => '', 118 /* I18N: a month in the Jewish calendar */ 119 1 => I18N::translateContext('NOMINATIVE', 'Tishrei'), 120 /* I18N: a month in the Jewish calendar */ 121 2 => I18N::translateContext('NOMINATIVE', 'Heshvan'), 122 /* I18N: a month in the Jewish calendar */ 123 3 => I18N::translateContext('NOMINATIVE', 'Kislev'), 124 /* I18N: a month in the Jewish calendar */ 125 4 => I18N::translateContext('NOMINATIVE', 'Tevet'), 126 /* I18N: a month in the Jewish calendar */ 127 5 => I18N::translateContext('NOMINATIVE', 'Shevat'), 128 /* I18N: a month in the Jewish calendar */ 129 6 => I18N::translateContext('NOMINATIVE', 'Adar I'), 130 /* I18N: a month in the Jewish calendar */ 131 7 => I18N::translateContext('NOMINATIVE', 'Adar'), 132 /* I18N: a month in the Jewish calendar */ 133 -7 => I18N::translateContext('NOMINATIVE', 'Adar II'), 134 /* I18N: a month in the Jewish calendar */ 135 8 => I18N::translateContext('NOMINATIVE', 'Nissan'), 136 /* I18N: a month in the Jewish calendar */ 137 9 => I18N::translateContext('NOMINATIVE', 'Iyar'), 138 /* I18N: a month in the Jewish calendar */ 139 10 => I18N::translateContext('NOMINATIVE', 'Sivan'), 140 /* I18N: a month in the Jewish calendar */ 141 11 => I18N::translateContext('NOMINATIVE', 'Tamuz'), 142 /* I18N: a month in the Jewish calendar */ 143 12 => I18N::translateContext('NOMINATIVE', 'Av'), 144 /* I18N: a month in the Jewish calendar */ 145 13 => I18N::translateContext('NOMINATIVE', 'Elul'), 146 ]; 147 } 148 149 if ($month_number === 7 && $leap_year) { 150 return $translated_month_names[-7]; 151 } else { 152 return $translated_month_names[$month_number]; 153 } 154 } 155 156 /** 157 * Full month name in genitive case. 158 * 159 * @param int $month_number 160 * @param bool $leap_year Some calendars use leap months 161 * 162 * @return string 163 */ 164 protected function monthNameGenitiveCase($month_number, $leap_year) 165 { 166 static $translated_month_names; 167 168 if ($translated_month_names === null) { 169 $translated_month_names = [ 170 0 => '', 171 /* I18N: a month in the Jewish calendar */ 172 1 => I18N::translateContext('GENITIVE', 'Tishrei'), 173 /* I18N: a month in the Jewish calendar */ 174 2 => I18N::translateContext('GENITIVE', 'Heshvan'), 175 /* I18N: a month in the Jewish calendar */ 176 3 => I18N::translateContext('GENITIVE', 'Kislev'), 177 /* I18N: a month in the Jewish calendar */ 178 4 => I18N::translateContext('GENITIVE', 'Tevet'), 179 /* I18N: a month in the Jewish calendar */ 180 5 => I18N::translateContext('GENITIVE', 'Shevat'), 181 /* I18N: a month in the Jewish calendar */ 182 6 => I18N::translateContext('GENITIVE', 'Adar I'), 183 /* I18N: a month in the Jewish calendar */ 184 7 => I18N::translateContext('GENITIVE', 'Adar'), 185 /* I18N: a month in the Jewish calendar */ 186 -7 => I18N::translateContext('GENITIVE', 'Adar II'), 187 /* I18N: a month in the Jewish calendar */ 188 8 => I18N::translateContext('GENITIVE', 'Nissan'), 189 /* I18N: a month in the Jewish calendar */ 190 9 => I18N::translateContext('GENITIVE', 'Iyar'), 191 /* I18N: a month in the Jewish calendar */ 192 10 => I18N::translateContext('GENITIVE', 'Sivan'), 193 /* I18N: a month in the Jewish calendar */ 194 11 => I18N::translateContext('GENITIVE', 'Tamuz'), 195 /* I18N: a month in the Jewish calendar */ 196 12 => I18N::translateContext('GENITIVE', 'Av'), 197 /* I18N: a month in the Jewish calendar */ 198 13 => I18N::translateContext('GENITIVE', 'Elul'), 199 ]; 200 } 201 202 if ($month_number === 7 && $leap_year) { 203 return $translated_month_names[-7]; 204 } else { 205 return $translated_month_names[$month_number]; 206 } 207 } 208 209 /** 210 * Full month name in locative case. 211 * 212 * @param int $month_number 213 * @param bool $leap_year Some calendars use leap months 214 * 215 * @return string 216 */ 217 protected function monthNameLocativeCase($month_number, $leap_year) 218 { 219 static $translated_month_names; 220 221 if ($translated_month_names === null) { 222 $translated_month_names = [ 223 0 => '', 224 /* I18N: a month in the Jewish calendar */ 225 1 => I18N::translateContext('LOCATIVE', 'Tishrei'), 226 /* I18N: a month in the Jewish calendar */ 227 2 => I18N::translateContext('LOCATIVE', 'Heshvan'), 228 /* I18N: a month in the Jewish calendar */ 229 3 => I18N::translateContext('LOCATIVE', 'Kislev'), 230 /* I18N: a month in the Jewish calendar */ 231 4 => I18N::translateContext('LOCATIVE', 'Tevet'), 232 /* I18N: a month in the Jewish calendar */ 233 5 => I18N::translateContext('LOCATIVE', 'Shevat'), 234 /* I18N: a month in the Jewish calendar */ 235 6 => I18N::translateContext('LOCATIVE', 'Adar I'), 236 /* I18N: a month in the Jewish calendar */ 237 7 => I18N::translateContext('LOCATIVE', 'Adar'), 238 /* I18N: a month in the Jewish calendar */ 239 -7 => I18N::translateContext('LOCATIVE', 'Adar II'), 240 /* I18N: a month in the Jewish calendar */ 241 8 => I18N::translateContext('LOCATIVE', 'Nissan'), 242 /* I18N: a month in the Jewish calendar */ 243 9 => I18N::translateContext('LOCATIVE', 'Iyar'), 244 /* I18N: a month in the Jewish calendar */ 245 10 => I18N::translateContext('LOCATIVE', 'Sivan'), 246 /* I18N: a month in the Jewish calendar */ 247 11 => I18N::translateContext('LOCATIVE', 'Tamuz'), 248 /* I18N: a month in the Jewish calendar */ 249 12 => I18N::translateContext('LOCATIVE', 'Av'), 250 /* I18N: a month in the Jewish calendar */ 251 13 => I18N::translateContext('LOCATIVE', 'Elul'), 252 ]; 253 } 254 255 if ($month_number === 7 && $leap_year) { 256 return $translated_month_names[-7]; 257 } else { 258 return $translated_month_names[$month_number]; 259 } 260 } 261 262 /** 263 * Full month name in instrumental case. 264 * 265 * @param int $month_number 266 * @param bool $leap_year Some calendars use leap months 267 * 268 * @return string 269 */ 270 protected function monthNameInstrumentalCase($month_number, $leap_year) 271 { 272 static $translated_month_names; 273 274 if ($translated_month_names === null) { 275 $translated_month_names = [ 276 0 => '', 277 /* I18N: a month in the Jewish calendar */ 278 1 => I18N::translateContext('INSTRUMENTAL', 'Tishrei'), 279 /* I18N: a month in the Jewish calendar */ 280 2 => I18N::translateContext('INSTRUMENTAL', 'Heshvan'), 281 /* I18N: a month in the Jewish calendar */ 282 3 => I18N::translateContext('INSTRUMENTAL', 'Kislev'), 283 /* I18N: a month in the Jewish calendar */ 284 4 => I18N::translateContext('INSTRUMENTAL', 'Tevet'), 285 /* I18N: a month in the Jewish calendar */ 286 5 => I18N::translateContext('INSTRUMENTAL', 'Shevat'), 287 /* I18N: a month in the Jewish calendar */ 288 6 => I18N::translateContext('INSTRUMENTAL', 'Adar I'), 289 /* I18N: a month in the Jewish calendar */ 290 7 => I18N::translateContext('INSTRUMENTAL', 'Adar'), 291 /* I18N: a month in the Jewish calendar */ 292 -7 => I18N::translateContext('INSTRUMENTAL', 'Adar II'), 293 /* I18N: a month in the Jewish calendar */ 294 8 => I18N::translateContext('INSTRUMENTAL', 'Nissan'), 295 /* I18N: a month in the Jewish calendar */ 296 9 => I18N::translateContext('INSTRUMENTAL', 'Iyar'), 297 /* I18N: a month in the Jewish calendar */ 298 10 => I18N::translateContext('INSTRUMENTAL', 'Sivan'), 299 /* I18N: a month in the Jewish calendar */ 300 11 => I18N::translateContext('INSTRUMENTAL', 'Tamuz'), 301 /* I18N: a month in the Jewish calendar */ 302 12 => I18N::translateContext('INSTRUMENTAL', 'Av'), 303 /* I18N: a month in the Jewish calendar */ 304 13 => I18N::translateContext('INSTRUMENTAL', 'Elul'), 305 ]; 306 } 307 308 if ($month_number === 7 && $leap_year) { 309 return $translated_month_names[-7]; 310 } else { 311 return $translated_month_names[$month_number]; 312 } 313 } 314 315 /** 316 * Abbreviated month name 317 * 318 * @param int $month_number 319 * @param bool $leap_year Some calendars use leap months 320 * 321 * @return string 322 */ 323 protected function monthNameAbbreviated($month_number, $leap_year) 324 { 325 return self::monthNameNominativeCase($month_number, $leap_year); 326 } 327 328 /** 329 * Which months follows this one? Calendars with leap-months should provide their own implementation. 330 * 331 * @return int[] 332 */ 333 protected function nextMonth() 334 { 335 if ($this->m == 6 && !$this->isLeapYear()) { 336 return [ 337 $this->y, 338 8, 339 ]; 340 } else { 341 return [ 342 $this->y + ($this->m == 13 ? 1 : 0), 343 ($this->m % 13) + 1, 344 ]; 345 } 346 } 347} 348