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 function formatDayZeros() { 43 if (WT_LOCALE == 'he') { 44 return $this->numberToHebrewNumerals($this->d); 45 } else { 46 return $this->d; 47 } 48 } 49 50 /** {@inheritdoc} */ 51 function formatDay() { 52 if (WT_LOCALE == 'he') { 53 return $this->numberToHebrewNumerals($this->d); 54 } else { 55 return $this->d; 56 } 57 } 58 59 /** {@inheritdoc} */ 60 function formatShortYear() { 61 if (WT_LOCALE == 'he') { 62 return $this->numberToHebrewNumerals($this->y % 1000); 63 } else { 64 return $this->y; 65 } 66 } 67 68 /** {@inheritdoc} */ 69 function formatLongYear() { 70 if (WT_LOCALE == 'he') { 71 return $this->numberToHebrewNumerals($this->y); 72 } else { 73 return $this->y; 74 } 75 } 76 77 /** {@inheritdoc} */ 78 public static function monthNameNominativeCase($month_number, $leap_year) { 79 static $translated_month_names; 80 81 if ($translated_month_names === null) { 82 $translated_month_names = array( 83 0 => '', 84 1 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tishrei'), 85 2 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Heshvan'), 86 3 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Kislev'), 87 4 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tevet'), 88 5 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Shevat'), 89 6 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar I'), 90 7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar'), 91 -7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Adar II'), 92 8 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Nissan'), 93 9 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Iyar'), 94 10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Sivan'), 95 11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Tamuz'), 96 12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Av'), 97 13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('NOMINATIVE', 'Elul'), 98 ); 99 } 100 101 if ($month_number === 7 && $leap_year) { 102 return $translated_month_names[-7]; 103 } else { 104 return $translated_month_names[$month_number]; 105 } 106 } 107 108 /** {@inheritdoc} */ 109 static function monthNameGenitiveCase($month_number, $leap_year) { 110 static $translated_month_names; 111 112 if ($translated_month_names === null) { 113 $translated_month_names = array( 114 0 => '', 115 1 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tishrei'), 116 2 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Heshvan'), 117 3 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Kislev'), 118 4 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tevet'), 119 5 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Shevat'), 120 6 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar I'), 121 7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar'), 122 -7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Adar II'), 123 8 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Nissan'), 124 9 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Iyar'), 125 10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Sivan'), 126 11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Tamuz'), 127 12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Av'), 128 13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('GENITIVE', 'Elul'), 129 ); 130 } 131 132 if ($month_number === 7 && $leap_year) { 133 return $translated_month_names[-7]; 134 } else { 135 return $translated_month_names[$month_number]; 136 } 137 } 138 139 /** {@inheritdoc} */ 140 protected static function monthNameLocativeCase($month_number, $leap_year) { 141 static $translated_month_names; 142 143 if ($translated_month_names === null) { 144 $translated_month_names = array( 145 0 => '', 146 1 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tishrei'), 147 2 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Heshvan'), 148 3 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Kislev'), 149 4 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tevet'), 150 5 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Shevat'), 151 6 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar I'), 152 7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar'), 153 -7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Adar II'), 154 8 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Nissan'), 155 9 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Iyar'), 156 10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Sivan'), 157 11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Tamuz'), 158 12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Av'), 159 13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('LOCATIVE', 'Elul'), 160 ); 161 } 162 163 if ($month_number === 7 && $leap_year) { 164 return $translated_month_names[-7]; 165 } else { 166 return $translated_month_names[$month_number]; 167 } 168 } 169 170 /** {@inheritdoc} */ 171 protected static function monthNameInstrumentalCase($month_number, $leap_year) { 172 static $translated_month_names; 173 174 if ($translated_month_names === null) { 175 $translated_month_names = array( 176 0 => '', 177 1 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tishrei'), 178 2 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Heshvan'), 179 3 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Kislev'), 180 4 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tevet'), 181 5 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Shevat'), 182 6 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar I'), 183 7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar'), 184 -7 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Adar II'), 185 8 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Nissan'), 186 9 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Iyar'), 187 10 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Sivan'), 188 11 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Tamuz'), 189 12 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Av'), 190 13 => /* I18N: a month in the Jewish calendar */ I18N::translateContext('INSTRUMENTAL', 'Elul'), 191 ); 192 } 193 194 if ($month_number === 7 && $leap_year) { 195 return $translated_month_names[-7]; 196 } else { 197 return $translated_month_names[$month_number]; 198 } 199 } 200 201 /** {@inheritdoc} */ 202 protected static function monthNameAbbreviated($month_number, $leap_year) { 203 return self::monthNameNominativeCase($month_number, $leap_year); 204 } 205 206 /** {@inheritdoc} */ 207 protected function nextMonth() { 208 if ($this->m == 6 && !$this->isLeapYear()) { 209 return array($this->y, 8); 210 } else { 211 return array($this->y + ($this->m == 13 ? 1 : 0), ($this->m % 13) + 1); 212 } 213 } 214 215 /** 216 * Convert a decimal number to hebrew - like roman numerals, but with extra punctuation and special rules. 217 * 218 * @param integer $num 219 * 220 * @return string 221 */ 222 protected static function numberToHebrewNumerals($num) { 223 $DISPLAY_JEWISH_THOUSANDS = false; 224 225 static $jHundreds = array("", "ק", "ר", "ש", "ת", "תק", "תר", "תש", "תת", "תתק"); 226 static $jTens = array("", "י", "כ", "ל", "מ", "נ", "ס", "ע", "פ", "צ"); 227 static $jTenEnds = array("", "י", "ך", "ל", "ם", "ן", "ס", "ע", "ף", "ץ"); 228 static $tavTaz = array("ט״ו", "ט״ז"); 229 static $jOnes = array("", "א", "ב", "ג", "ד", "ה", "ו", "ז", "ח", "ט"); 230 231 $shortYear = $num % 1000; //discard thousands 232 //next check for all possible single Hebrew digit years 233 $singleDigitYear = ($shortYear < 11 || ($shortYear < 100 && $shortYear % 10 == 0) || ($shortYear <= 400 && $shortYear % 100 == 0)); 234 $thousands = (int) ($num / 1000); //get # thousands 235 $sb = ""; 236 //append thousands to String 237 if ($num % 1000 == 0) { 238 // in year is 5000, 4000 etc 239 $sb .= $jOnes[$thousands]; 240 $sb .= self::GERSH; 241 $sb .= " "; 242 $sb .= self::ALAFIM; //add # of thousands plus word thousand (overide alafim boolean) 243 } elseif ($DISPLAY_JEWISH_THOUSANDS) { 244 // if alafim boolean display thousands 245 $sb .= $jOnes[$thousands]; 246 $sb .= self::GERSH; //append thousands quote 247 $sb .= " "; 248 } 249 $num = $num % 1000; //remove 1000s 250 $hundreds = (int) ($num / 100); // # of hundreds 251 $sb .= $jHundreds[$hundreds]; //add hundreds to String 252 $num = $num % 100; //remove 100s 253 if ($num == 15) { 254 $sb .= $tavTaz[0]; 255 } else if ($num == 16) { 256 $sb .= $tavTaz[1]; 257 } else { 258 $tens = (int) ($num / 10); 259 if ($num % 10 == 0) { 260 if ($singleDigitYear == false) { 261 $sb .= $jTenEnds[$tens]; // use end letters so that for example 5750 will end with an end nun 262 } else { 263 $sb .= $jTens[$tens]; // use standard letters so that for example 5050 will end with a regular nun 264 } 265 } else { 266 $sb .= $jTens[$tens]; 267 $num = $num % 10; 268 $sb .= $jOnes[$num]; 269 } 270 } 271 if ($singleDigitYear == true) { 272 // Append single quote 273 $sb .= self::GERSH; 274 } else { 275 // Append double quote before last digit 276 $pos1 = strlen($sb) - 2; 277 $sb = substr($sb, 0, $pos1) . self::GERSHAYIM . substr($sb, $pos1); 278 // Replace double gershayim with single instance 279 $sb = str_replace(self::GERSHAYIM . self::GERSHAYIM, self::GERSHAYIM, $sb); 280 } 281 282 return $sb; 283 } 284} 285