Completed
Push — develop ( 90c1a9...626f47 )
by Greg
01:53
created

Shim::calFromJd()   C

Complexity

Conditions 8
Paths 6

Size

Total Lines 28
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 18
nc 6
nop 2
dl 0
loc 28
rs 5.3846
c 0
b 0
f 0
1
<?php
2
namespace Fisharebest\ExtCalendar;
3
4
use InvalidArgumentException;
5
6
/**
7
 * class Shim - PHP implementations of functions from the PHP calendar extension.
8
 *
9
 * @link      http://php.net/manual/en/book.calendar.php
10
 *
11
 * @author    Greg Roach <[email protected]>
12
 * @copyright (c) 2014-2017 Greg Roach
13
 * @license   This program is free software: you can redistribute it and/or modify
14
 *            it under the terms of the GNU General Public License as published by
15
 *            the Free Software Foundation, either version 3 of the License, or
16
 *            (at your option) any later version.
17
 *
18
 *            This program is distributed in the hope that it will be useful,
19
 *            but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 *            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 *            GNU General Public License for more details.
22
 *
23
 *            You should have received a copy of the GNU General Public License
24
 *            along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
 */
26
class Shim {
0 ignored issues
show
Coding Style introduced by
Shim does not seem to conform to the naming convention (Utils?$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
27
	/** @var FrenchCalendar */
28
	private static $french_calendar;
29
30
	/** @var GregorianCalendar */
31
	private static $gregorian_calendar;
32
33
	/** @var JewishCalendar */
34
	private static $jewish_calendar;
35
36
	/** @var JulianCalendar */
37
	private static $julian_calendar;
38
39
	/**
40
	 * English names for the days of the week.
41
	 *
42
	 * @var string[]
43
	 */
44
	private static $DAY_NAMES = array(
45
		'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
46
	);
47
48
	/**
49
	 * Abbreviated English names for the days of the week.
50
	 *
51
	 * @var string[]
52
	 */
53
	private static $DAY_NAMES_SHORT = array(
54
		'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat',
55
	);
56
57
	/** @var string[] Names of the months of the Gregorian/Julian calendars */
58
	private static $MONTH_NAMES = array(
59
		'', 'January', 'February', 'March', 'April', 'May', 'June',
60
		'July', 'August', 'September', 'October', 'November', 'December',
61
	);
62
63
	/** @var string[] Abbreviated names of the months of the Gregorian/Julian calendars */
64
	private static $MONTH_NAMES_SHORT = array(
65
		'', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
66
	);
67
68
	/** @var string[] Name of the months of the French calendar */
69
	private static $MONTH_NAMES_FRENCH = array(
70
		'', 'Vendemiaire', 'Brumaire', 'Frimaire', 'Nivose', 'Pluviose', 'Ventose',
71
		'Germinal', 'Floreal', 'Prairial', 'Messidor', 'Thermidor', 'Fructidor', 'Extra'
72
	);
73
74
	/** @var string[] Names of the months of the Jewish calendar in a non-leap year */
75
	private static $MONTH_NAMES_JEWISH = array(
76
		'', 'Tishri', 'Heshvan', 'Kislev', 'Tevet', 'Shevat', 'Adar',
77
		'Adar', 'Nisan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', 'Elul',
78
	);
79
80
	/** @var string[] Names of the months of the Jewish calendar in a leap year */
81
	private static $MONTH_NAMES_JEWISH_LEAP_YEAR = array(
82
		'', 'Tishri', 'Heshvan', 'Kislev', 'Tevet', 'Shevat', 'Adar I',
83
		'Adar II', 'Nisan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', 'Elul',
84
	);
85
86
	/** @var string[] Names of the months of the Jewish calendar (before PHP bug 54254 was fixed) */
87
	private static $MONTH_NAMES_JEWISH_54254 = array(
88
		'', 'Tishri', 'Heshvan', 'Kislev', 'Tevet', 'Shevat', 'AdarI',
89
		'AdarII', 'Nisan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', 'Elul',
90
	);
91
92
	/**
93
	 * Create the necessary shims to emulate the ext/calendar package.
94
	 *
95
	 * @return void
96
	 */
97
	public static function create() {
98
		self::$french_calendar    = new FrenchCalendar;
99
		self::$gregorian_calendar = new GregorianCalendar;
100
		self::$jewish_calendar    = new JewishCalendar(array(
101
			JewishCalendar::EMULATE_BUG_54254 => self::shouldEmulateBug54254(),
102
		));
103
		self::$julian_calendar    = new JulianCalendar;
104
	}
105
106
	/**
107
	 * Do we need to emulate PHP bug #54254?
108
	 *
109
	 * This bug relates to the names used for months 6 and 7 in the Jewish calendar.
110
	 *
111
	 * It was fixed in PHP 5.5.0
112
	 *
113
	 * @link https://bugs.php.net/bug.php?id=54254
114
	 *
115
	 * @return boolean
116
	 */
117
	public static function shouldEmulateBug54254() {
118
		return version_compare(PHP_VERSION, '5.5.0', '<');
119
	}
120
121
	/**
122
	 * Do we need to emulate PHP bug #67960?
123
	 *
124
	 * This bug relates to the constants CAL_DOW_SHORT and CAL_DOW_LONG.
125
	 *
126
	 * It was fixed in PHP 5.6.5 and 5.5.21
127
	 *
128
	 * @link https://bugs.php.net/bug.php?id=67960
129
	 * @link https://github.com/php/php-src/pull/806
130
	 *
131
	 * @return boolean
132
	 */
133
	public static function shouldEmulateBug67960() {
134
		return version_compare(PHP_VERSION, '5.5.21', '<') || version_compare(PHP_VERSION, '5.6.0', '>=') && version_compare(PHP_VERSION, '5.6.5', '<') ;
135
	}
136
137
	/**
138
	 * Do we need to emulate PHP bug #67976?
139
	 *
140
	 * This bug relates to the number of days in the month 13 of year 14 in
141
	 * the French calendar.
142
	 *
143
	 * It was fixed in PHP 5.6.25 and 7.0.10
144
	 *
145
	 * @link https://bugs.php.net/bug.php?id=67976
146
	 *
147
	 * @return boolean
148
	 */
149
	public static function shouldEmulateBug67976() {
150
		return version_compare(PHP_VERSION, '5.6.25', '<') || version_compare(PHP_VERSION, '7.0.0', '>=') && version_compare(PHP_VERSION, '7.0.11', '<') ;
151
	}
152
153
	/**
154
	 * Return the number of days in a month for a given year and calendar.
155
	 *
156
	 * Shim implementation of cal_days_in_month()
157
	 *
158
	 * @link https://php.net/cal_days_in_month
159
	 * @link https://bugs.php.net/bug.php?id=67976
160
	 *
161
	 * @param integer $calendar_id
162
	 * @param integer $month
163
	 * @param integer $year
164
	 *
165
	 * @return integer|boolean The number of days in the specified month, or false on error
166
	 */
167
	public static function calDaysInMonth($calendar_id, $month, $year) {
168
		switch ($calendar_id) {
169
		case CAL_FRENCH:
170
			return self::calDaysInMonthFrench($year, $month);
171
172
		case CAL_GREGORIAN:
173
			return self::calDaysInMonthCalendar(self::$gregorian_calendar, $year, $month);
174
175
		case CAL_JEWISH:
176
			return self::calDaysInMonthCalendar(self::$jewish_calendar, $year, $month);
177
178
		case CAL_JULIAN:
179
			return self::calDaysInMonthCalendar(self::$julian_calendar, $year, $month);
180
181
		default:
182
			return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING);
183
		}
184
	}
185
186
	/**
187
	 * Calculate the number of days in a month in a specified (Gregorian or Julian) calendar.
188
	 *
189
	 * @param CalendarInterface $calendar
190
	 * @param integer           $year
191
	 * @param integer           $month
192
	 *
193
	 * @return integer|boolean
194
	 */
195
	private static function calDaysInMonthCalendar(CalendarInterface $calendar, $year, $month) {
196
		try {
197
			return $calendar->daysInMonth($year, $month);
198
		} catch (InvalidArgumentException $ex) {
199
			return trigger_error('invalid date.', E_USER_WARNING);
200
		}
201
	}
202
203
	/**
204
	 * Calculate the number of days in a month in the French calendar.
205
	 *
206
	 * Mimic PHP’s validation of the parameters
207
	 *
208
	 * @param integer $year
209
	 * @param integer $month
210
	 *
211
	 * @return integer|boolean
212
	 */
213
	private static function calDaysInMonthFrench($year, $month) {
214
		if ($month == 13 && $year == 14 && self::shouldEmulateBug67976()) {
215
			return -2380948;
216
		} elseif ($year > 14) {
217
			return trigger_error('invalid date.', E_USER_WARNING);
218
		} else {
219
			return self::calDaysInMonthCalendar(self::$french_calendar, $year, $month);
220
		}
221
	}
222
223
	/**
224
	 * Converts from Julian Day Count to a supported calendar.
225
	 *
226
	 * Shim implementation of cal_from_jd()
227
	 *
228
	 * @link https://php.net/cal_from_jd
229
	 *
230
	 * @param integer $julian_day  Julian Day number
231
	 * @param integer $calendar_id Calendar constant
232
	 *
233
	 * @return array|boolean
234
	 */
235
	public static function calFromJd($julian_day, $calendar_id) {
236
		switch ($calendar_id) {
237
		case CAL_FRENCH:
238
			return self::calFromJdCalendar($julian_day, self::jdToFrench($julian_day), self::$MONTH_NAMES_FRENCH, self::$MONTH_NAMES_FRENCH);
239
240
		case CAL_GREGORIAN:
241
			return self::calFromJdCalendar($julian_day, self::jdToGregorian($julian_day), self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT);
242
243
		case CAL_JEWISH:
244
			$months = self::jdMonthNameJewishMonths($julian_day);
245
246
			$cal = self::calFromJdCalendar($julian_day, self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846), $months, $months);
247
248
			if (($julian_day < 347998 || $julian_day > 324542846) && !self::shouldEmulateBug67976()) {
249
				$cal['dow'] = null;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 11 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
250
				$cal['dayname'] = '';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
251
				$cal['abbrevdayname'] = '';
252
			}
253
254
			return $cal;
255
256
		case CAL_JULIAN:
257
			return self::calFromJdCalendar($julian_day, self::jdToJulian($julian_day), self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT);
258
259
		default:
260
			return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING);
261
		}
262
	}
263
264
	/**
265
	 * Convert a Julian day number to a calendar and provide details.
266
	 *
267
	 * @param integer  $julian_day
268
	 * @param string   $mdy
269
	 * @param string[] $months
270
	 * @param string[] $months_short
271
	 *
272
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|integer>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
273
	 */
274
	private static function calFromJdCalendar($julian_day, $mdy, $months, $months_short) {
275
		list($month, $day, $year) = explode('/', $mdy);
276
277
		return array(
278
			'date'          => $month . '/' . $day . '/' . $year,
279
			'month'         => (int) $month,
280
			'day'           => (int) $day,
281
			'year'          => (int) $year,
282
			'dow'           => self::jdDayOfWeek($julian_day, 0),
283
			'abbrevdayname' => self::jdDayOfWeek($julian_day, 2),
284
			'dayname'       => self::jdDayOfWeek($julian_day, 1),
285
			'abbrevmonth'   => $months_short[$month],
286
			'monthname'     => $months[$month],
287
		);
288
	}
289
290
	/**
291
	 * Returns information about a particular calendar.
292
	 *
293
	 * Shim implementation of cal_info()
294
	 *
295
	 * @link https://php.net/cal_info
296
	 *
297
	 * @param integer $calendar_id
298
	 *
299
	 * @return array|boolean
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string[]|in...olean>|boolean>|boolean.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
300
	 */
301
	public static function calInfo($calendar_id) {
302
		switch ($calendar_id) {
303
		case CAL_FRENCH:
304
			return self::calInfoCalendar(self::$MONTH_NAMES_FRENCH, self::$MONTH_NAMES_FRENCH, 30, 'French', 'CAL_FRENCH');
305
306
		case CAL_GREGORIAN:
307
			return self::calInfoCalendar(self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT, 31, 'Gregorian', 'CAL_GREGORIAN');
308
309
		case CAL_JEWISH:
310
			$months = self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH_LEAP_YEAR;
311
312
			return self::calInfoCalendar($months, $months, 30, 'Jewish', 'CAL_JEWISH');
313
314
		case CAL_JULIAN:
315
			return self::calInfoCalendar(self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT, 31, 'Julian', 'CAL_JULIAN');
316
317
		case -1:
318
			return array(
319
				CAL_GREGORIAN => self::calInfo(CAL_GREGORIAN),
320
				CAL_JULIAN    => self::calInfo(CAL_JULIAN),
321
				CAL_JEWISH    => self::calInfo(CAL_JEWISH),
322
				CAL_FRENCH    => self::calInfo(CAL_FRENCH),
323
			);
324
325
		default:
326
			return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING);
327
		}
328
	}
329
330
	/**
331
	 * Returns information about the French calendar.
332
	 *
333
	 * @param string[] $month_names
334
	 * @param string[] $month_names_short
335
	 * @param integer  $max_days_in_month
336
	 * @param string   $calendar_name
337
	 * @param string   $calendar_symbol
338
	 *
339
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string[]|integer|string>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
340
	 */
341
	private static function calInfoCalendar($month_names, $month_names_short, $max_days_in_month, $calendar_name, $calendar_symbol) {
342
		return array(
343
			'months'         => array_slice($month_names, 1, null, true),
344
			'abbrevmonths'   => array_slice($month_names_short, 1, null, true),
345
			'maxdaysinmonth' => $max_days_in_month,
346
			'calname'        => $calendar_name,
347
			'calsymbol'      => $calendar_symbol,
348
		);
349
	}
350
351
	/**
352
	 *  Converts from a supported calendar to Julian Day Count
353
	 *
354
	 * Shim implementation of cal_to_jd()
355
	 *
356
	 * @link https://php.net/cal_to_jd
357
	 *
358
	 * @param integer $calendar_id
359
	 * @param integer $month
360
	 * @param integer $day
361
	 * @param integer $year
362
	 *
363
	 * @return integer|boolean
364
	 */
365
	public static function calToJd($calendar_id, $month, $day, $year) {
366
		switch ($calendar_id) {
367
		case CAL_FRENCH:
368
			return self::frenchToJd($month, $day, $year);
369
370
		case CAL_GREGORIAN:
371
			return self::gregorianToJd($month, $day, $year);
372
373
		case CAL_JEWISH:
374
			return self::jewishToJd($month, $day, $year);
375
376
		case CAL_JULIAN:
377
			return self::julianToJd($month, $day, $year);
378
379
		default:
380
			return trigger_error('invalid calendar ID ' . $calendar_id . '.', E_USER_WARNING);
381
		}
382
	}
383
384
	/**
385
	 * Get Unix timestamp for midnight on Easter of a given year.
386
	 *
387
	 * Shim implementation of easter_date()
388
	 *
389
	 * @link https://php.net/easter_date
390
	 *
391
	 * @param integer $year
392
	 *
393
	 * @return integer|boolean
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
394
	 */
395
	public static function easterDate($year) {
396
		if ($year < 1970 || $year > 2037) {
397
			return trigger_error('This function is only valid for years between 1970 and 2037 inclusive', E_USER_WARNING);
398
		}
399
400
		$days = self::$gregorian_calendar->easterDays($year);
401
402
		// Calculate time-zone offset
403
		$date_time      = new \DateTime('now', new \DateTimeZone(date_default_timezone_get()));
404
		$offset_seconds = (int) $date_time->format('Z');
405
406
		if ($days < 11) {
407
			return self::jdtounix(self::$gregorian_calendar->ymdToJd($year, 3, $days + 21)) - $offset_seconds;
408
		} else {
409
			return self::jdtounix(self::$gregorian_calendar->ymdToJd($year, 4, $days - 10)) - $offset_seconds;
410
		}
411
	}
412
413
	/**
414
	 * Get number of days after March 21 on which Easter falls for a given year.
415
	 *
416
	 * Shim implementation of easter_days()
417
	 *
418
	 * @link https://php.net/easter_days
419
	 *
420
	 * @param integer $year
421
	 * @param integer $method Use the Julian or Gregorian calendar
422
	 *
423
	 * @return integer
424
	 */
425
	public static function easterDays($year, $method) {
426
		if (
427
			$method == CAL_EASTER_ALWAYS_JULIAN ||
428
			$method == CAL_EASTER_ROMAN && $year <= 1582 ||
429
			$year <= 1752 && $method != CAL_EASTER_ROMAN && $method != CAL_EASTER_ALWAYS_GREGORIAN
430
		) {
431
			return self::$julian_calendar->easterDays($year);
432
		} else {
433
			return self::$gregorian_calendar->easterDays($year);
434
		}
435
	}
436
437
	/**
438
	 * Converts a date from the French Republican Calendar to a Julian Day Count.
439
	 *
440
	 * Shim implementation of FrenchToJD()
441
	 *
442
	 * @link https://php.net/FrenchToJD
443
	 *
444
	 * @param integer $month
445
	 * @param integer $day
446
	 * @param integer $year
447
	 *
448
	 * @return integer
449
	 */
450
	public static function frenchToJd($month, $day, $year) {
451
		if ($year <= 0) {
452
			return 0;
453
		} else {
454
			return self::$french_calendar->ymdToJd($year, $month, $day);
455
		}
456
	}
457
458
	/**
459
	 * Converts a Gregorian date to Julian Day Count.
460
	 *
461
	 * Shim implementation of GregorianToJD()
462
	 *
463
	 * @link https://php.net/GregorianToJD
464
	 *
465
	 * @param integer $month
466
	 * @param integer $day
467
	 * @param integer $year
468
	 *
469
	 * @return integer
470
	 */
471
	public static function gregorianToJd($month, $day, $year) {
472
		if ($year == 0) {
473
			return 0;
474
		} else {
475
			return self::$gregorian_calendar->ymdToJd($year, $month, $day);
476
		}
477
	}
478
479
	/**
480
	 * Returns the day of the week.
481
	 *
482
	 * Shim implementation of JDDayOfWeek()
483
	 *
484
	 * @link https://php.net/JDDayOfWeek
485
	 * @link https://bugs.php.net/bug.php?id=67960
486
	 *
487
	 * @param integer $julian_day
488
	 * @param integer $mode
489
	 *
490
	 * @return integer|string
491
	 */
492
	public static function jdDayOfWeek($julian_day, $mode) {
493
		$day_of_week = ($julian_day + 1) % 7;
494
		if ($day_of_week < 0) {
495
			$day_of_week += 7;
496
		}
497
498
		switch ($mode) {
499
		case 1: // 1, not CAL_DOW_LONG - see bug 67960
500
			return self::$DAY_NAMES[$day_of_week];
501
502
		case 2: // 2, not CAL_DOW_SHORT - see bug 67960
503
			return self::$DAY_NAMES_SHORT[$day_of_week];
504
505
		default: // CAL_DOW_DAYNO or anything else
506
			return $day_of_week;
507
		}
508
	}
509
510
	/**
511
	 * Returns a month name.
512
	 *
513
	 * Shim implementation of JDMonthName()
514
	 *
515
	 * @link https://php.net/JDMonthName
516
	 *
517
	 * @param integer $julian_day
518
	 * @param integer $mode
519
	 *
520
	 * @return string
521
	 */
522
	public static function jdMonthName($julian_day, $mode) {
523
		switch ($mode) {
524
		case CAL_MONTH_GREGORIAN_LONG:
525
			return self::jdMonthNameCalendar(self::$gregorian_calendar, $julian_day, self::$MONTH_NAMES);
526
527
		case CAL_MONTH_JULIAN_LONG:
528
			return self::jdMonthNameCalendar(self::$julian_calendar, $julian_day, self::$MONTH_NAMES);
529
530
		case CAL_MONTH_JULIAN_SHORT:
531
			return self::jdMonthNameCalendar(self::$julian_calendar, $julian_day, self::$MONTH_NAMES_SHORT);
532
533
		case CAL_MONTH_JEWISH:
534
			return self::jdMonthNameCalendar(self::$jewish_calendar, $julian_day, self::jdMonthNameJewishMonths($julian_day));
535
536
		case CAL_MONTH_FRENCH:
537
			return self::jdMonthNameCalendar(self::$french_calendar, $julian_day, self::$MONTH_NAMES_FRENCH);
538
539
		case CAL_MONTH_GREGORIAN_SHORT:
540
		default:
541
			return self::jdMonthNameCalendar(self::$gregorian_calendar, $julian_day, self::$MONTH_NAMES_SHORT);
542
		}
543
	}
544
545
	/**
546
	 * Calculate the month-name for a given julian day, in a given calendar,
547
	 * with given set of month names.
548
	 *
549
	 * @param CalendarInterface $calendar
550
	 * @param integer           $julian_day
551
	 * @param string[]          $months
552
	 *
553
	 * @return string
554
	 */
555
	private static function jdMonthNameCalendar(CalendarInterface $calendar, $julian_day, $months) {
556
		list(, $month) = $calendar->jdToYmd($julian_day);
557
558
		return $months[$month];
559
	}
560
561
	/**
562
	 * Determine which month names to use for the Jewish calendar.
563
	 *
564
	 * @param integer $julian_day
565
	 *
566
	 * @return string[]
567
	 */
568
	private static function jdMonthNameJewishMonths($julian_day) {
569
		list(, , $year) = explode('/', self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846));
570
571
		if (self::$jewish_calendar->isLeapYear($year)) {
572
			return self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH_LEAP_YEAR;
573
		} else {
574
			return self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH;
575
		}
576
	}
577
578
	/**
579
	 * Convert a Julian day in a specific calendar to a day/month/year.
580
	 *
581
	 * Julian days outside the specified range are returned as “0/0/0”.
582
	 *
583
	 * @param CalendarInterface $calendar
584
	 * @param integer           $julian_day
585
	 * @param integer           $min_jd
586
	 * @param integer           $max_jd
587
	 *
588
	 * @return string
589
	 */
590
	private static function jdToCalendar(CalendarInterface $calendar, $julian_day, $min_jd, $max_jd) {
591
		if ($julian_day >= $min_jd && $julian_day <= $max_jd) {
592
			list($year, $month, $day) = $calendar->jdToYmd($julian_day);
593
594
			return $month . '/' . $day . '/' . $year;
595
		} else {
596
			return '0/0/0';
597
		}
598
	}
599
600
	/**
601
	 * Converts a Julian Day Count to the French Republican Calendar.
602
	 *
603
	 * Shim implementation of JDToFrench()
604
	 *
605
	 * @link https://php.net/JDToFrench
606
	 *
607
	 * @param integer $julian_day A Julian Day number
608
	 *
609
	 * @return string A string of the form "month/day/year"
610
	 */
611
	public static function jdToFrench($julian_day) {
612
		// JDToFrench() converts years 1 to 14 inclusive, even though the calendar
613
		// officially ended on 10 Nivôse 14 (JD 2380687, 31st December 1805 Gregorian).
614
		return self::jdToCalendar(self::$french_calendar, $julian_day, 2375840, 2380952);
615
	}
616
617
	/**
618
	 * Converts Julian Day Count to Gregorian date.
619
	 *
620
	 * Shim implementation of JDToGregorian()
621
	 *
622
	 * @link https://php.net/JDToGregorian
623
	 *
624
	 * @param integer $julian_day A Julian Day number
625
	 *
626
	 * @return string A string of the form "month/day/year"
627
	 */
628
	public static function jdToGregorian($julian_day) {
629
		// PHP has different limits on 32 and 64 bit systems.
630
		$MAX_JD = PHP_INT_SIZE == 4 ? 536838866 : 2305843009213661906;
631
632
		return self::jdToCalendar(self::$gregorian_calendar, $julian_day, 1, $MAX_JD);
633
	}
634
635
	/**
636
	 * Converts a Julian day count to a Jewish calendar date.
637
	 *
638
	 * Shim implementation of JdtoJjewish()
639
	 *
640
	 * @link https://php.net/JdtoJewish
641
	 *
642
	 * @param integer $julian_day A Julian Day number
643
	 * @param boolean $hebrew     If true, the date is returned in Hebrew text
644
	 * @param integer $fl         If $hebrew is true, then add alafim and gereshayim to the text
645
	 *
646
	 * @return string|boolean A string of the form "month/day/year", or false on error
647
	 */
648
	public static function jdToJewish($julian_day, $hebrew, $fl) {
649
		if ($hebrew) {
650
			if ($julian_day < 347998 || $julian_day > 4000075) {
651
				return trigger_error('Year out of range (0-9999).', E_USER_WARNING);
652
			}
653
654
			return self::$jewish_calendar->jdToHebrew(
655
				$julian_day,
656
				(bool)($fl & CAL_JEWISH_ADD_ALAFIM_GERESH),
657
				(bool)($fl & CAL_JEWISH_ADD_ALAFIM),
658
				(bool)($fl & CAL_JEWISH_ADD_GERESHAYIM)
659
			);
660
		} else {
661
			// The upper limit is hard-coded into PHP to prevent numeric overflow on 32 bit systems.
662
			return self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846);
663
		}
664
	}
665
666
	/**
667
	 * Converts a Julian Day Count to a Julian Calendar Date.
668
	 *
669
	 * Shim implementation of JDToJulian()
670
	 *
671
	 * @link https://php.net/JDToJulian
672
	 *
673
	 * @param integer $julian_day A Julian Day number
674
	 *
675
	 * @return string A string of the form "month/day/year"
676
	 */
677
	public static function jdToJulian($julian_day) {
678
		// PHP has different limits on 32 and 64 bit systems.
679
		$MAX_JD = PHP_INT_SIZE == 4 ? 536838829 : 784368370349;
680
681
		return self::jdToCalendar(self::$julian_calendar, $julian_day, 1, $MAX_JD);
682
	}
683
684
	/**
685
	 * Convert Julian Day to Unix timestamp.
686
	 *
687
	 * Shim implementation of jdtounix()
688
	 *
689
	 * @link https://php.net/jdtounix
690
	 *
691
	 * @param integer $julian_day
692
	 *
693
	 * @return integer|false
694
	 */
695
	public static function jdToUnix($julian_day) {
696
		if ($julian_day >= 2440588 && $julian_day <= 2465343) {
697
			return (int) ($julian_day - 2440588) * 86400;
698
		} else {
699
			return false;
700
		}
701
	}
702
703
	/**
704
	 * Converts a date in the Jewish Calendar to Julian Day Count.
705
	 *
706
	 * Shim implementation of JewishToJD()
707
	 *
708
	 * @link https://php.net/JewishToJD
709
	 *
710
	 * @param integer $month
711
	 * @param integer $day
712
	 * @param integer $year
713
	 *
714
	 * @return integer
715
	 */
716
	public static function jewishToJd($month, $day, $year) {
717
		if ($year <= 0) {
718
			return 0;
719
		} else {
720
			return self::$jewish_calendar->ymdToJd($year, $month, $day);
721
		}
722
	}
723
724
	/**
725
	 * Converts a Julian Calendar date to Julian Day Count.
726
	 *
727
	 * Shim implementation of JdToJulian()
728
	 *
729
	 * @link https://php.net/JdToJulian
730
	 *
731
	 * @param integer $month
732
	 * @param integer $day
733
	 * @param integer $year
734
	 *
735
	 * @return integer
736
	 */
737
	public static function julianToJd($month, $day, $year) {
738
		if ($year == 0) {
739
			return 0;
740
		} else {
741
			return self::$julian_calendar->ymdToJd($year, $month, $day);
742
		}
743
	}
744
745
	/**
746
	 * Convert Unix timestamp to Julian Day.
747
	 *
748
	 * Shim implementation of unixtojd()
749
	 *
750
	 * @link https://php.net/unixtojd
751
	 *
752
	 * @param integer $timestamp
753
	 *
754
	 * @return false|integer
755
	 */
756
	public static function unixToJd($timestamp) {
757
		if ($timestamp < 0) {
758
			return false;
759
		} else {
760
			// Convert timestamp based on local timezone
761
			return self::GregorianToJd(gmdate('n', $timestamp), gmdate('j', $timestamp), gmdate('Y', $timestamp));
762
		}
763
	}
764
}
765