I18N_Arabic

# Source for file Date.php

Documentation is available at Date.php

1. <?php
2. /**
3. * ----------------------------------------------------------------------
4. *
5. * Copyright (c) 2006-2016 Khaled Al-Sham'aa.
6. *
7. * http://www.ar-php.org
8. *
9. * PHP Version 5
10. *
11. * ----------------------------------------------------------------------
12. *
13. * LICENSE
14. *
15. * This program is open source product; you can redistribute it and/or
16. * modify it under the terms of the GNU Lesser General Public License (LGPL)
17. * as published by the Free Software Foundation; either version 3
18. * of the License, or (at your option) any later version.
19. *
20. * This program is distributed in the hope that it will be useful,
21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23. * GNU Lesser General Public License for more details.
24. *
25. * You should have received a copy of the GNU Lesser General Public License
26. * along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>.
27. *
28. * ----------------------------------------------------------------------
29. *
30. * Class Name: Arabic Date
31. *
32. * Filename: Date.php
33. *
34. * Original Author(s): Khaled Al-Sham'aa <khaled@ar-php.org>
35. *
36. * Purpose: Arabic customization for PHP date function
37. *
38. * ----------------------------------------------------------------------
39. *
40. * Arabic Date
41. *
42. * PHP class for Arabic and Islamic customization of PHP date function. It
43. * can convert UNIX timestamp into string in Arabic as well as convert it into
44. * Hijri calendar
45. *
46. * The Islamic Calendar:
47. *
48. * The Islamic calendar is purely lunar and consists of twelve alternating months
49. * of 30 and 29 days, with the final 29 day month extended to 30 days during leap
50. * years. Leap years follow a 30 year cycle and occur in years 1, 5, 7, 10, 13, 16,
51. * 18, 21, 24, 26, and 29. The calendar begins on Friday, July 16th, 622 C.E. in
52. * the Julian calendar, Julian day 1948439.5, the day of Muhammad's separate from
53. * Mecca to Medina, the first day of the first month of year 1 A.H.--"Anno Hegira".
54. *
55. * Each cycle of 30 years thus contains 19 normal years of 354 days and 11 leap
56. * years of 355, so the average length of a year is therefore
57. * ((19 x 354) + (11 x 355)) / 30 = 354.365... days, with a mean length of month of
58. * 1/12 this figure, or 29.53055... days, which closely approximates the mean
59. * synodic month (time from new Moon to next new Moon) of 29.530588 days, with the
60. * calendar only slipping one day with respect to the Moon every 2525 years. Since
61. * the calendar is fixed to the Moon, not the solar year, the months shift with
62. * respect to the seasons, with each month beginning about 11 days earlier in each
63. * successive solar year.
64. *
65. * The convert presented here is the most commonly used civil calendar in the
66. * Islamic world; for religious purposes months are defined to start with the
67. * first observation of the crescent of the new Moon.
68. *
69. * The Julian Calendar:
70. *
71. * The Julian calendar was proclaimed by Julius Casar in 46 B.C. and underwent
72. * several modifications before reaching its final form in 8 C.E. The Julian
73. * calendar differs from the Gregorian only in the determination of leap years,
74. * lacking the correction for years divisible by 100 and 400 in the Gregorian
75. * calendar. In the Julian calendar, any positive year is a leap year if divisible
76. * by 4. (Negative years are leap years if when divided by 4 a remainder of 3
77. * results.) Days are considered to begin at midnight.
78. *
79. * In the Julian calendar the average year has a length of 365.25 days. compared to
80. * the actual solar tropical year of 365.24219878 days. The calendar thus
81. * accumulates one day of error with respect to the solar year every 128 years.
82. * Being a purely solar calendar, no attempt is made to synchronise the start of
83. * months to the phases of the Moon.
84. *
85. * The Gregorian Calendar:
86. *
87. * The Gregorian calendar was proclaimed by Pope Gregory XIII and took effect in
88. * most Catholic states in 1582, in which October 4, 1582 of the Julian calendar
89. * was followed by October 15 in the new calendar, correcting for the accumulated
90. * discrepancy between the Julian calendar and the equinox as of that date. When
91. * comparing historical dates, it's important to note that the Gregorian calendar,
92. * used universally today in Western countries and in international commerce, was
93. * adopted at different times by different countries. Britain and her colonies
94. * (including what is now the United States), did not switch to the Gregorian
95. * calendar until 1752, when Wednesday 2nd September in the Julian calendar dawned
96. * as Thursday the 14th in the Gregorian.
97. *
98. * The Gregorian calendar is a minor correction to the Julian. In the Julian
99. * calendar every fourth year is a leap year in which February has 29, not 28 days,
100. * but in the Gregorian, years divisible by 100 are not leap years unless they are
101. * also divisible by 400. How prescient was Pope Gregory! Whatever the problems of
102. * Y2K, they won't include sloppy programming which assumes every year divisible by
103. * 4 is a leap year since 2000, unlike the previous and subsequent years divisible
104. * by 100, is a leap year. As in the Julian calendar, days are considered to begin
105. * at midnight.
106. *
107. * The average length of a year in the Gregorian calendar is 365.2425 days compared
108. * to the actual solar tropical year (time from equinox to equinox) of 365.24219878
109. * days, so the calendar accumulates one day of error with respect to the solar year
110. * about every 3300 years. As a purely solar calendar, no attempt is made to
111. * synchronise the start of months to the phases of the Moon.
112. *
113. * date -- Format a local time/date
114. * string date ( string format, int timestamp);
115. *
116. * Returns a string formatted according to the given format string using the given
117. * integer timestamp or the current local time if no timestamp is given. In
118. * otherwords, timestamp is optional and defaults to the value of time().
119. *
120. * Example:
121. * <code>
122. * date_default_timezone_set('UTC');
123. * $time = time();
124. *
125. * echo date('l dS F Y h:i:s A', $time);
126. * echo '<br /><br />';
127. *
128. * include('./I18N/Arabic.php');
129. * $obj = new I18N_Arabic('Date');
130. *
131. * echo $obj->date('l dS F Y h:i:s A', $time);
132. * echo '<br /><br />';
133. *
134. * $obj->setMode(2);
135. * echo $obj->date('l dS F Y h:i:s A', $time);
136. * echo '<br /><br />';
137. *
138. * $obj->setMode(3);
139. * echo $obj->date('l dS F Y h:i:s A', $time);
140. * echo '<br /><br />';
141. *
142. * $obj->setMode(4);
143. * echo $obj->date('l dS F Y h:i:s A', $time);
144. * </code>
145. *
146. * @category I18N
147. * @package I18N_Arabic
148. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
149. * @copyright 2006-2016 Khaled Al-Sham'aa
150. *
151. * @license LGPL <http://www.gnu.org/licenses/lgpl.txt>
152. * @link http://www.ar-php.org
153. */
155. /**
156. * This PHP class is an Arabic customization for PHP date function
157. *
158. * @category I18N
159. * @package I18N_Arabic
160. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
161. * @copyright 2006-2016 Khaled Al-Sham'aa
162. *
163. * @license LGPL <http://www.gnu.org/licenses/lgpl.txt>
164. * @link http://www.ar-php.org
165. */
166. class I18N_Arabic_Date
167. {
168. private $_mode = 1;
169. private $_xml = null;
171. /**
172. * Loads initialize values
173. *
174. * @ignore
175. */
176. public function __construct()
177. {
178. $this->_xml = simplexml_load_file(dirname(__FILE__).'/data/ArDate.xml');
179. }
181. /**
182. * Setting value for $mode scalar
183. *
184. * @param integer $mode Output mode of date function where:
185. * 1) Hijri format (Islamic calendar)
186. * 2) Arabic month names used in Middle East countries
187. * 3) Arabic Transliteration of Gregorian month names
188. * 4) Both of 2 and 3 formats together
189. * 5) Libya style
190. * 6) Algeria and Tunis style
191. * 7) Morocco style
192. * 8) Hijri format (Islamic calendar) in English
193. *
194. * @return object $this to build a fluent interface
195. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
196. */
197. public function setMode($mode = 1)
198. {
199. $mode = (int) $mode;
201. if ($mode > 0 && $mode < 9) {
202. $this->_mode = $mode;
203. }
205. return $this;
206. }
208. /**
209. * Getting $mode value that refer to output mode format
210. * 1) Hijri format (Islamic calendar)
211. * 2) Arabic month names used in Middle East countries
212. * 3) Arabic Transliteration of Gregorian month names
213. * 4) Both of 2 and 3 formats together
214. * 5) Libyan way
215. * 6) Algeria and Tunis style
216. * 7) Morocco style
217. * 8) Hijri format (Islamic calendar) in English
218. *
219. * @return Integer Value of $mode properity
220. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
221. */
222. public function getMode()
223. {
224. return $this->_mode;
225. }
227. /**
228. * Format a local time/date in Arabic string
229. *
230. * @param string $format Format string (same as PHP date function)
231. * @param integer $timestamp Unix timestamp
232. * @param integer $correction To apply correction factor (+/- 1-2) to
233. * standard hijri calendar
234. *
235. * @return string Format Arabic date string according to given format string
236. * using the given integer timestamp or the current local
237. * time if no timestamp is given.
238. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
239. */
240. public function date($format, $timestamp, $correction = 0)
241. {
242. if ($this->_mode == 1 || $this->_mode == 8) {
243. if ($this->_mode == 1) {
244. foreach ($this->_xml->ar_hj_month->month as $month) {
245. $hj_txt_month["{$month['id']}"] = (string)$month;
246. }
247. }
249. if ($this->_mode == 8) {
250. foreach ($this->_xml->en_hj_month->month as $month) {
251. $hj_txt_month["{$month['id']}"] = (string)$month;
252. }
253. }
255. $patterns = array();
256. $replacements = array();
258. array_push($patterns, 'Y');
259. array_push($replacements, 'x1');
260. array_push($patterns, 'y');
261. array_push($replacements, 'x2');
262. array_push($patterns, 'M');
263. array_push($replacements, 'x3');
264. array_push($patterns, 'F');
265. array_push($replacements, 'x3');
266. array_push($patterns, 'n');
267. array_push($replacements, 'x4');
268. array_push($patterns, 'm');
269. array_push($replacements, 'x5');
270. array_push($patterns, 'j');
271. array_push($replacements, 'x6');
272. array_push($patterns, 'd');
273. array_push($replacements, 'x7');
275. if ($this->_mode == 8) {
276. array_push($patterns, 'S');
277. array_push($replacements, '');
278. }
280. $format = str_replace($patterns, $replacements, $format);
282. $str = date($format, $timestamp);
283. if ($this->_mode == 1) {
284. $str = $this->en2ar($str);
285. }
287. $timestamp = $timestamp + 3600*24*$correction;
288. list($Y, $M, $D) = explode(' ', date('Y m d', $timestamp));
290. list($hj_y, $hj_m, $hj_d) = $this->hjConvert($Y, $M, $D);
292. $patterns = array();
293. $replacements = array();
295. array_push($patterns, 'x1');
296. array_push($replacements, $hj_y);
297. array_push($patterns, 'x2');
298. array_push($replacements, substr($hj_y, -2));
299. array_push($patterns, 'x3');
300. array_push($replacements, $hj_txt_month[$hj_m]);
301. array_push($patterns, 'x4');
302. array_push($replacements, $hj_m);
303. array_push($patterns, 'x5');
304. array_push($replacements, sprintf('%02d', $hj_m));
305. array_push($patterns, 'x6');
306. array_push($replacements, $hj_d);
307. array_push($patterns, 'x7');
308. array_push($replacements, sprintf('%02d', $hj_d));
310. $str = str_replace($patterns, $replacements, $str);
311. } elseif ($this->_mode == 5) {
312. $year = date('Y', $timestamp);
313. $year -= 632;
314. $yr = substr("$year", -2);
316. $format = str_replace('Y', $year, $format);
317. $format = str_replace('y', $yr, $format);
319. $str = date($format, $timestamp);
320. $str = $this->en2ar($str);
322. } else {
323. $str = date($format, $timestamp);
324. $str = $this->en2ar($str);
325. }
327. if (0) {
328. if ($outputCharset == null) {
329. $outputCharset = $main->getOutputCharset();
330. }
331. $str = $main->coreConvert($str, 'utf-8', $outputCharset);
332. }
334. return $str;
335. }
337. /**
338. * Translate English date/time terms into Arabic langauge
339. *
340. * @param string $str Date/time string using English terms
341. *
342. * @return string Date/time string using Arabic terms
343. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
344. */
345. protected function en2ar($str)
346. {
347. $patterns = array();
348. $replacements = array();
350. $str = strtolower($str);
352. foreach ($this->_xml->xpath("//en_day/mode[@id='full']/search") as $day) {
353. array_push($patterns, (string)$day);
354. }
356. foreach ($this->_xml->ar_day->replace as $day) {
357. array_push($replacements, (string)$day);
358. }
360. foreach (
361. $this->_xml->xpath("//en_month/mode[@id='full']/search") as $month
362. ) {
363. array_push($patterns, (string)$month);
364. }
366. $replacements = array_merge(
367. $replacements,
368. $this->arabicMonths($this->_mode)
369. );
371. foreach ($this->_xml->xpath("//en_day/mode[@id='short']/search") as $day) {
372. array_push($patterns, (string)$day);
373. }
375. foreach ($this->_xml->ar_day->replace as $day) {
376. array_push($replacements, (string)$day);
377. }
379. foreach ($this->_xml->xpath("//en_month/mode[@id='short']/search") as $m) {
380. array_push($patterns, (string)$m);
381. }
383. $replacements = array_merge(
384. $replacements,
385. $this->arabicMonths($this->_mode)
386. );
388. foreach (
389. $this->_xml->xpath("//preg_replace[@function='en2ar']/pair") as $p
390. ) {
391. array_push($patterns, (string)$p->search);
392. array_push($replacements, (string)$p->replace);
393. }
395. $str = str_replace($patterns, $replacements, $str);
397. return $str;
398. }
400. /**
401. * Add Arabic month names to the replacement array
402. *
403. * @param integer $mode Naming mode of months in Arabic where:
404. * 2) Arabic month names used in Middle East countries
405. * 3) Arabic Transliteration of Gregorian month names
406. * 4) Both of 2 and 3 formats together
407. * 5) Libya style
408. * 6) Algeria and Tunis style
409. * 7) Morocco style
410. *
411. * @return array Arabic month names in selected style
412. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
413. */
414. protected function arabicMonths($mode)
415. {
416. $replacements = array();
418. foreach (
419. $this->_xml->xpath("//ar_month/mode[@id=$mode]/replace") as $month
420. ) {
421. array_push($replacements, (string)$month);
422. }
424. return $replacements;
425. }
427. /**
428. * Convert given Gregorian date into Hijri date
429. *
430. * @param integer $Y Year Gregorian year
431. * @param integer $M Month Gregorian month
432. * @param integer $D Day Gregorian day
433. *
434. * @return array Hijri date [int Year, int Month, int Day](Islamic calendar)
435. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
436. */
437. protected function hjConvert($Y, $M, $D)
438. {
439. if (function_exists('GregorianToJD')) {
440. $jd = GregorianToJD($M, $D, $Y);
441. } else {
442. $jd = $this->gregToJd($M, $D, $Y);
443. }
445. list($year, $month, $day) = $this->jdToIslamic($jd);
447. return array($year, $month, $day);
448. }
450. /**
451. * Convert given Julian day into Hijri date
452. *
453. * @param integer $jd Julian day
454. *
455. * @return array Hijri date [int Year, int Month, int Day](Islamic calendar)
456. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
457. */
458. protected function jdToIslamic($jd)
459. {
460. $l = (int)$jd - 1948440 + 10632;
461. $n = (int)(($l - 1) / 10631);
462. $l = $l - 10631 * $n + 354;
463. $j = (int)((10985 - $l) / 5316) * (int)((50 * $l) / 17719)
464. + (int)($l / 5670) * (int)((43 * $l) / 15238);
465. $l = $l - (int)((30 - $j) / 15) * (int)((17719 * $j) / 50)
466. - (int)($j / 16) * (int)((15238 * $j) / 43) + 29;
467. $m = (int)((24 * $l) / 709);
468. $d = $l - (int)((709 * $m) / 24);
469. $y = (int)(30 * $n + $j - 30);
471. return array($y, $m, $d);
472. }
474. /**
475. * Convert given Hijri date into Julian day
476. *
477. * @param integer $year Year Hijri year
478. * @param integer $month Month Hijri month
479. * @param integer $day Day Hijri day
480. *
481. * @return integer Julian day
482. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
483. */
484. protected function islamicToJd($year, $month, $day)
485. {
486. $jd = (int)((11 * $year + 3) / 30) + (int)(354 * $year) + (int)(30 * $month)
487. - (int)(($month - 1) / 2) + $day + 1948440 - 385;
488. return $jd;
489. }
491. /**
492. * Converts a Gregorian date to Julian Day Count
493. *
494. * @param integer $m The month as a number from 1 (for January)
495. * to 12 (for December)
496. * @param integer $d The day as a number from 1 to 31
497. * @param integer $y The year as a number between -4714 and 9999
498. *
499. * @return integer The julian day for the given gregorian date as an integer
500. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
501. */
502. protected function gregToJd ($m, $d, $y)
503. {
504. if ($m < 3) {
505. $y--;
506. $m += 12;
507. }
509. if (($y < 1582) || ($y == 1582 && $m < 10)
510. || ($y == 1582 && $m == 10 && $d <= 15)
511. ) {
512. // This is ignored in the GregorianToJD PHP function!
513. $b = 0;
514. } else {
515. $a = (int)($y / 100);
516. $b = 2 - $a + (int)($a / 4);
517. }
519. $jd = (int)(365.25 * ($y + 4716)) + (int)(30.6001 * ($m + 1))
520. + $d + $b - 1524.5;
522. return round($jd);
523. }
525. /**
526. * Calculate Hijri calendar correction using Um-Al-Qura calendar information
527. *
528. * @param integer $time Unix timestamp
529. *
530. * @return integer Correction factor to fix Hijri calendar calculation using
531. * Um-Al-Qura calendar information
532. * @author Khaled Al-Sham'aa <khaled@ar-php.org>
533. */
534. public function dateCorrection ($time)
535. {
536. $calc = $time - $this->date('j', $time) * 3600 * 24;
538. $file = dirname(__FILE__).'/data/um_alqoura.txt';
540. $content = file_get_contents($file);
542. $y = $this->date('Y', $time);
543. $m = $this->date('n', $time);
544. $offset = (($y-1420) * 12 + $m) * 11;
546. $d = substr($content, $offset, 2);
547. $m = substr($content, $offset+3, 2);
548. $y = substr($content, $offset+6, 4);
550. $real = mktime(0, 0, 0, $m, $d, $y);
552. $diff = (int)(($calc - $real) / (3600 * 24));
554. return $diff;
555. }
556. }

Documentation generated on Fri, 01 Jan 2016 10:25:57 +0200 by phpDocumentor 1.4.0