-
Notifications
You must be signed in to change notification settings - Fork 0
/
Date.php
400 lines (342 loc) · 11.8 KB
/
Date.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
<?php
namespace ArabyPHP\Date;
class Date
{
/**
* @var int
*/
private $_mode = 1;
/**
* @var null
*/
private $_xml = null;
/**
* Loads initialize values.
*
* @ignore
*/
public function __construct()
{
$this->_xml = simplexml_load_file(__DIR__.'/data/ArDate.xml');
}
/**
* Setting value for $mode scalar.
*
* @param int $mode Output mode of date function where:
* 1) Hijri format (Islamic calendar)
* 2) Arabic month names used in Middle East countries
* 3) Arabic Transliteration of Gregorian month names
* 4) Both of 2 and 3 formats together
* 5) Libya style
* 6) Algeria and Tunis style
* 7) Morocco style
* 8) Hijri format (Islamic calendar) in English
*
* @return object $this to build a fluent interface
*
*/
public function setDateMode($mode = 1)
{
$mode = (int) $mode;
if ($mode > 0 && $mode < 9) {
$this->_mode = $mode;
}
return $this;
}
/**
* Getting $mode value that refer to output mode format
* 1) Hijri format (Islamic calendar)
* 2) Arabic month names used in Middle East countries
* 3) Arabic Transliteration of Gregorian month names
* 4) Both of 2 and 3 formats together
* 5) Libyan way
* 6) Algeria and Tunis style
* 7) Morocco style
* 8) Hijri format (Islamic calendar) in English.
*
* @return int Value of $mode properity
*
*/
public function getDateMode()
{
return $this->_mode;
}
/**
* Format a local time/date in Arabic string.
*
* @param string $format Format string (same as PHP date function)
* @param int $timestamp Unix timestamp
* @param int $correction To apply correction factor (+/- 1-2) to
* standard hijri calendar
*
* @return string Format Arabic date string according to given format string
* using the given integer timestamp or the current local
* time if no timestamp is given.
*
*/
public function date($format, $timestamp, $correction = 0)
{
if ($this->_mode == 1 || $this->_mode == 8) {
if ($this->_mode == 1) {
foreach ($this->_xml->ar_hj_month->month as $month) {
$hj_txt_month["{$month['id']}"] = (string) $month;
}
}
if ($this->_mode == 8) {
foreach ($this->_xml->en_hj_month->month as $month) {
$hj_txt_month["{$month['id']}"] = (string) $month;
}
}
$patterns = [];
$replacements = [];
array_push($patterns, 'Y');
array_push($replacements, 'x1');
array_push($patterns, 'y');
array_push($replacements, 'x2');
array_push($patterns, 'M');
array_push($replacements, 'x3');
array_push($patterns, 'F');
array_push($replacements, 'x3');
array_push($patterns, 'n');
array_push($replacements, 'x4');
array_push($patterns, 'm');
array_push($replacements, 'x5');
array_push($patterns, 'j');
array_push($replacements, 'x6');
array_push($patterns, 'd');
array_push($replacements, 'x7');
if ($this->_mode == 8) {
array_push($patterns, 'S');
array_push($replacements, '');
}
$format = str_replace($patterns, $replacements, $format);
$str = date($format, $timestamp);
if ($this->_mode == 1) {
$str = $this->en2ar($str);
}
$timestamp = $timestamp + 3600 * 24 * $correction;
list($Y, $M, $D) = explode(' ', date('Y m d', $timestamp));
list($hj_y, $hj_m, $hj_d) = $this->hjConvert($Y, $M, $D);
$patterns = [];
$replacements = [];
array_push($patterns, 'x1');
array_push($replacements, $hj_y);
array_push($patterns, 'x2');
array_push($replacements, substr($hj_y, -2));
array_push($patterns, 'x3');
array_push($replacements, $hj_txt_month[$hj_m]);
array_push($patterns, 'x4');
array_push($replacements, $hj_m);
array_push($patterns, 'x5');
array_push($replacements, sprintf('%02d', $hj_m));
array_push($patterns, 'x6');
array_push($replacements, $hj_d);
array_push($patterns, 'x7');
array_push($replacements, sprintf('%02d', $hj_d));
$str = str_replace($patterns, $replacements, $str);
} elseif ($this->_mode == 5) {
$year = date('Y', $timestamp);
$year -= 632;
$yr = substr("$year", -2);
$format = str_replace('Y', $year, $format);
$format = str_replace('y', $yr, $format);
$str = date($format, $timestamp);
$str = $this->en2ar($str);
} else {
$str = date($format, $timestamp);
$str = $this->en2ar($str);
}
if (0) {
if ($outputCharset == null) {
$outputCharset = $main->getOutputCharset();
}
$str = $main->coreConvert($str, 'utf-8', $outputCharset);
}
return $str;
}
/**
* Translate English date/time terms into Arabic langauge.
*
* @param string $str Date/time string using English terms
*
* @return string Date/time string using Arabic terms
*
*/
protected function en2ar($str)
{
$patterns = [];
$replacements = [];
$str = strtolower($str);
foreach ($this->_xml->xpath("//en_day/mode[@id='full']/search") as $day) {
array_push($patterns, (string) $day);
}
foreach ($this->_xml->ar_day->replace as $day) {
array_push($replacements, (string) $day);
}
foreach (
$this->_xml->xpath("//en_month/mode[@id='full']/search") as $month
) {
array_push($patterns, (string) $month);
}
$replacements = array_merge(
$replacements,
$this->arabicMonths($this->_mode)
);
foreach ($this->_xml->xpath("//en_day/mode[@id='short']/search") as $day) {
array_push($patterns, (string) $day);
}
foreach ($this->_xml->ar_day->replace as $day) {
array_push($replacements, (string) $day);
}
foreach ($this->_xml->xpath("//en_month/mode[@id='short']/search") as $m) {
array_push($patterns, (string) $m);
}
$replacements = array_merge(
$replacements,
$this->arabicMonths($this->_mode)
);
foreach (
$this->_xml->xpath("//preg_replace[@function='en2ar']/pair") as $p
) {
array_push($patterns, (string) $p->search);
array_push($replacements, (string) $p->replace);
}
$str = str_replace($patterns, $replacements, $str);
return $str;
}
/**
* Add Arabic month names to the replacement array.
*
* @param int $mode Naming mode of months in Arabic where:
* 2) Arabic month names used in Middle East countries
* 3) Arabic Transliteration of Gregorian month names
* 4) Both of 2 and 3 formats together
* 5) Libya style
* 6) Algeria and Tunis style
* 7) Morocco style
*
* @return array Arabic month names in selected style
*
*/
protected function arabicMonths($mode)
{
$replacements = [];
foreach (
$this->_xml->xpath("//ar_month/mode[@id=$mode]/replace") as $month
) {
array_push($replacements, (string) $month);
}
return $replacements;
}
/**
* Convert given Gregorian date into Hijri date.
*
* @param int $Y Year Gregorian year
* @param int $M Month Gregorian month
* @param int $D Day Gregorian day
*
* @return array Hijri date [int Year, int Month, int Day](Islamic calendar)
*
*/
protected function hjConvert($Y, $M, $D)
{
if (function_exists('GregorianToJD')) {
$jd = gregoriantojd($M, $D, $Y);
} else {
$jd = $this->gregToJd($M, $D, $Y);
}
list($year, $month, $day) = $this->jdToIslamic($jd);
return [$year, $month, $day];
}
/**
* Convert given Julian day into Hijri date.
*
* @param int $jd Julian day
*
* @return array Hijri date [int Year, int Month, int Day](Islamic calendar)
*
*/
protected function jdToIslamic($jd)
{
$l = (int) $jd - 1948440 + 10632;
$n = (int) (($l - 1) / 10631);
$l = $l - 10631 * $n + 354;
$j = (int) ((10985 - $l) / 5316) * (int) ((50 * $l) / 17719)
+ (int) ($l / 5670) * (int) ((43 * $l) / 15238);
$l = $l - (int) ((30 - $j) / 15) * (int) ((17719 * $j) / 50)
- (int) ($j / 16) * (int) ((15238 * $j) / 43) + 29;
$m = (int) ((24 * $l) / 709);
$d = $l - (int) ((709 * $m) / 24);
$y = (int) (30 * $n + $j - 30);
return [$y, $m, $d];
}
/**
* Convert given Hijri date into Julian day.
*
* @param int $year Year Hijri year
* @param int $month Month Hijri month
* @param int $day Day Hijri day
*
* @return int Julian day
*
*/
protected function islamicToJd($year, $month, $day)
{
$jd = (int) ((11 * $year + 3) / 30) + (int) (354 * $year) + (int) (30 * $month)
- (int) (($month - 1) / 2) + $day + 1948440 - 385;
return $jd;
}
/**
* Converts a Gregorian date to Julian Day Count.
*
* @param int $m The month as a number from 1 (for January)
* to 12 (for December)
* @param int $d The day as a number from 1 to 31
* @param int $y The year as a number between -4714 and 9999
*
* @return int The julian day for the given gregorian date as an integer
*
*/
protected function gregToJd($m, $d, $y)
{
if ($m < 3) {
$y--;
$m += 12;
}
if (($y < 1582) || ($y == 1582 && $m < 10)
|| ($y == 1582 && $m == 10 && $d <= 15)
) {
// This is ignored in the GregorianToJD PHP function!
$b = 0;
} else {
$a = (int) ($y / 100);
$b = 2 - $a + (int) ($a / 4);
}
$jd = (int) (365.25 * ($y + 4716)) + (int) (30.6001 * ($m + 1))
+ $d + $b - 1524.5;
return round($jd);
}
/**
* Calculate Hijri calendar correction using Um-Al-Qura calendar information.
*
* @param int $time Unix timestamp
*
* @return int Correction factor to fix Hijri calendar calculation using
* Um-Al-Qura calendar information
*
*/
public function dateCorrection($time)
{
$calc = $time - $this->date('j', $time) * 3600 * 24;
$content = file_get_contents(dirname(__FILE__).'/../../resources/data/um_alqoura.txt');
$y = $this->date('Y', $time);
$m = $this->date('n', $time);
$offset = (($y - 1420) * 12 + $m) * 11;
$d = substr($content, $offset, 2);
$m = substr($content, $offset + 3, 2);
$y = substr($content, $offset + 6, 4);
$real = mktime(0, 0, 0, $m, $d, $y);
$diff = (int) (($calc - $real) / (3600 * 24));
return $diff;
}
}