1<?php 2namespace Fisharebest\Webtrees; 3 4/** 5 * webtrees: online genealogy 6 * Copyright (C) 2015 webtrees development team 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19use Fisharebest\ExtCalendar\JewishCalendar; 20 21/** 22 * Class JewishDate - Definitions for the Jewish calendar 23 */ 24class JewishDate extends CalendarDate { 25 const CALENDAR_ESCAPE = '@#DHEBREW@'; 26 const MONTHS_IN_YEAR = 13; 27 const CAL_START_JD = 347998; // 01 TSH 0001 = @#JULIAN@ 7 OCT 3761B.C. 28 const GERSHAYIM = '״'; 29 const GERSH = '׳'; 30 const ALAFIM = 'אלפים'; 31 32 /** {@inheritdoc} */ 33 public static $MONTH_ABBREV = array('' => 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); 34 35 /** {@inheritdoc} */ 36 public function __construct($date) { 37 $this->calendar = new JewishCalendar; 38 parent::__construct($date); 39 } 40 41 /** {@inheritdoc} */ 42 public static function calendarName() { 43 return /* I18N: The Hebrew/Jewish calendar */ 44 I18N::translate('Jewish'); 45 } 46 47 /** {@inheritdoc} */ 48 function formatDayZeros() { 49 if (WT_LOCALE == 'he') { 50 return $this->numberToHebrewNumerals($this->d); 51 } else { 52 return $this->d; 53 } 54 } 55 56 /** {@inheritdoc} */ 57 function formatDay() { 58 if (WT_LOCALE == 'he') { 59 return $this->numberToHebrewNumerals($this->d); 60 } else { 61 return $this->d; 62 } 63 } 64 65 /** {@inheritdoc} */ 66 function formatShortYear() { 67 if (WT_LOCALE == 'he') { 68 return $this->numberToHebrewNumerals($this->y % 1000); 69 } else { 70 return $this->y; 71 } 72 } 73 74 /** {@inheritdoc} */ 75 function formatLongYear() { 76 if (WT_LOCALE == 'he') { 77 return $this->numberToHebrewNumerals($this->y); 78 } else { 79 return $this->y; 80 } 81 } 82 83 /** {@inheritdoc} */ 84 public static function monthNameNominativeCase($month_number, $leap_year) { 85 static $translated_month_names; 86 87 if ($translated_month_names === null) { 88 $translated_month_names = array( 89 0 => '', 90 1 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tishrei'), 91 2 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Heshvan'), 92 3 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Kislev'), 93 4 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tevet'), 94 5 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Shevat'), 95 6 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar I'), 96 7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar'), 97 -7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar II'), 98 8 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Nissan'), 99 9 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Iyar'), 100 10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Sivan'), 101 11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tamuz'), 102 12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Av'), 103 13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Elul'), 104 ); 105 } 106 107 if ($month_number === 7 && $leap_year) { 108 return $translated_month_names[-7]; 109 } else { 110 return $translated_month_names[$month_number]; 111 } 112 } 113 114 /** {@inheritdoc} */ 115 static function monthNameGenitiveCase($month_number, $leap_year) { 116 static $translated_month_names; 117 118 if ($translated_month_names === null) { 119 $translated_month_names = array( 120 0 => '', 121 1 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tishrei'), 122 2 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Heshvan'), 123 3 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Kislev'), 124 4 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tevet'), 125 5 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Shevat'), 126 6 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar I'), 127 7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar'), 128 -7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar II'), 129 8 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Nissan'), 130 9 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Iyar'), 131 10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Sivan'), 132 11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tamuz'), 133 12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Av'), 134 13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Elul'), 135 ); 136 } 137 138 if ($month_number === 7 && $leap_year) { 139 return $translated_month_names[-7]; 140 } else { 141 return $translated_month_names[$month_number]; 142 } 143 } 144 145 /** {@inheritdoc} */ 146 protected static function monthNameLocativeCase($month_number, $leap_year) { 147 static $translated_month_names; 148 149 if ($translated_month_names === null) { 150 $translated_month_names = array( 151 0 => '', 152 1 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tishrei'), 153 2 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Heshvan'), 154 3 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Kislev'), 155 4 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tevet'), 156 5 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Shevat'), 157 6 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar I'), 158 7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar'), 159 -7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar II'), 160 8 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Nissan'), 161 9 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Iyar'), 162 10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Sivan'), 163 11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tamuz'), 164 12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Av'), 165 13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Elul'), 166 ); 167 } 168 169 if ($month_number === 7 && $leap_year) { 170 return $translated_month_names[-7]; 171 } else { 172 return $translated_month_names[$month_number]; 173 } 174 } 175 176 /** {@inheritdoc} */ 177 protected static function monthNameInstrumentalCase($month_number, $leap_year) { 178 static $translated_month_names; 179 180 if ($translated_month_names === null) { 181 $translated_month_names = array( 182 0 => '', 183 1 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tishrei'), 184 2 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Heshvan'), 185 3 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Kislev'), 186 4 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tevet'), 187 5 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Shevat'), 188 6 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar I'), 189 7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar'), 190 -7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar II'), 191 8 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Nissan'), 192 9 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Iyar'), 193 10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Sivan'), 194 11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tamuz'), 195 12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Av'), 196 13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Elul'), 197 ); 198 } 199 200 if ($month_number === 7 && $leap_year) { 201 return $translated_month_names[-7]; 202 } else { 203 return $translated_month_names[$month_number]; 204 } 205 } 206 207 /** {@inheritdoc} */ 208 protected static function monthNameAbbreviated($month_number, $leap_year) { 209 return self::monthNameNominativeCase($month_number, $leap_year); 210 } 211 212 /** {@inheritdoc} */ 213 protected function nextMonth() { 214 if ($this->m == 6 && !$this->isLeapYear()) { 215 return array($this->y, 8); 216 } else { 217 return array($this->y + ($this->m == 13 ? 1 : 0), ($this->m % 13) + 1); 218 } 219 } 220 221 /** 222 * Convert a decimal number to hebrew - like roman numerals, but with extra punctuation and special rules. 223 * 224 * @param integer $num 225 * 226 * @return string 227 */ 228 protected static function numberToHebrewNumerals($num) { 229 $DISPLAY_JEWISH_THOUSANDS = false; 230 231 static $jHundreds = array("", "ק", "ר", "ש", "ת", "תק", "תר", "תש", "תת", "תתק"); 232 static $jTens = array("", "י", "כ", "ל", "מ", "נ", "ס", "ע", "פ", "צ"); 233 static $jTenEnds = array("", "י", "ך", "ל", "ם", "ן", "ס", "ע", "ף", "ץ"); 234 static $tavTaz = array("ט״ו", "ט״ז"); 235 static $jOnes = array("", "א", "ב", "ג", "ד", "ה", "ו", "ז", "ח", "ט"); 236 237 $shortYear = $num % 1000; //discard thousands 238 //next check for all possible single Hebrew digit years 239 $singleDigitYear = ($shortYear < 11 || ($shortYear < 100 && $shortYear % 10 == 0) || ($shortYear <= 400 && $shortYear % 100 == 0)); 240 $thousands = (int) ($num / 1000); //get # thousands 241 $sb = ""; 242 //append thousands to String 243 if ($num % 1000 == 0) { 244 // in year is 5000, 4000 etc 245 $sb .= $jOnes[$thousands]; 246 $sb .= self::GERSH; 247 $sb .= " "; 248 $sb .= self::ALAFIM; //add # of thousands plus word thousand (overide alafim boolean) 249 } elseif ($DISPLAY_JEWISH_THOUSANDS) { 250 // if alafim boolean display thousands 251 $sb .= $jOnes[$thousands]; 252 $sb .= self::GERSH; //append thousands quote 253 $sb .= " "; 254 } 255 $num = $num % 1000; //remove 1000s 256 $hundreds = (int) ($num / 100); // # of hundreds 257 $sb .= $jHundreds[$hundreds]; //add hundreds to String 258 $num = $num % 100; //remove 100s 259 if ($num == 15) { 260 $sb .= $tavTaz[0]; 261 } else if ($num == 16) { 262 $sb .= $tavTaz[1]; 263 } else { 264 $tens = (int) ($num / 10); 265 if ($num % 10 == 0) { 266 if ($singleDigitYear == false) { 267 $sb .= $jTenEnds[$tens]; // use end letters so that for example 5750 will end with an end nun 268 } else { 269 $sb .= $jTens[$tens]; // use standard letters so that for example 5050 will end with a regular nun 270 } 271 } else { 272 $sb .= $jTens[$tens]; 273 $num = $num % 10; 274 $sb .= $jOnes[$num]; 275 } 276 } 277 if ($singleDigitYear == true) { 278 // Append single quote 279 $sb .= self::GERSH; 280 } else { 281 // Append double quote before last digit 282 $pos1 = strlen($sb) - 2; 283 $sb = substr($sb, 0, $pos1) . self::GERSHAYIM . substr($sb, $pos1); 284 // Replace double gershayim with single instance 285 $sb = str_replace(self::GERSHAYIM . self::GERSHAYIM, self::GERSHAYIM, $sb); 286 } 287 288 return $sb; 289 } 290} 291