Completed
Push — develop ( b6d6fd...b7f617 )
by Greg
01:53
created

Shim::mod()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 2
dl 0
loc 10
rs 9.4285
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.24', '<') || 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
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|integer>|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...
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
			return self::calFromJdCalendar($julian_day, self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846), $months, $months);
247
248
		case CAL_JULIAN:
249
			return self::calFromJdCalendar($julian_day, self::jdToJulian($julian_day), self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT);
250
251
		default:
252
			return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING);
253
		}
254
	}
255
256
	/**
257
	 * Convert a Julian day number to a calendar and provide details.
258
	 *
259
	 * @param integer  $julian_day
260
	 * @param string   $mdy
261
	 * @param string[] $months
262
	 * @param string[] $months_short
263
	 *
264
	 * @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...
265
	 */
266
	private static function calFromJdCalendar($julian_day, $mdy, $months, $months_short) {
267
		list($month, $day, $year) = explode('/', $mdy);
268
269
		return array(
270
			'date'          => $month . '/' . $day . '/' . $year,
271
			'month'         => (int) $month,
272
			'day'           => (int) $day,
273
			'year'          => (int) $year,
274
			'dow'           => self::jdDayOfWeek($julian_day, 0),
275
			'abbrevdayname' => self::jdDayOfWeek($julian_day, 2),
276
			'dayname'       => self::jdDayOfWeek($julian_day, 1),
277
			'abbrevmonth'   => $months_short[$month],
278
			'monthname'     => $months[$month],
279
		);
280
	}
281
282
	/**
283
	 * Returns information about a particular calendar.
284
	 *
285
	 * Shim implementation of cal_info()
286
	 *
287
	 * @link https://php.net/cal_info
288
	 *
289
	 * @param integer $calendar_id
290
	 *
291
	 * @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...
292
	 */
293
	public static function calInfo($calendar_id) {
294
		switch ($calendar_id) {
295
		case CAL_FRENCH:
296
			return self::calInfoCalendar(self::$MONTH_NAMES_FRENCH, self::$MONTH_NAMES_FRENCH, 30, 'French', 'CAL_FRENCH');
297
298
		case CAL_GREGORIAN:
299
			return self::calInfoCalendar(self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT, 31, 'Gregorian', 'CAL_GREGORIAN');
300
301
		case CAL_JEWISH:
302
			$months = self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH_LEAP_YEAR;
303
304
			return self::calInfoCalendar($months, $months, 30, 'Jewish', 'CAL_JEWISH');
305
306
		case CAL_JULIAN:
307
			return self::calInfoCalendar(self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT, 31, 'Julian', 'CAL_JULIAN');
308
309
		case -1:
310
			return array(
311
				CAL_GREGORIAN => self::calInfo(CAL_GREGORIAN),
312
				CAL_JULIAN    => self::calInfo(CAL_JULIAN),
313
				CAL_JEWISH    => self::calInfo(CAL_JEWISH),
314
				CAL_FRENCH    => self::calInfo(CAL_FRENCH),
315
			);
316
317
		default:
318
			return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING);
319
		}
320
	}
321
322
	/**
323
	 * Returns information about the French calendar.
324
	 *
325
	 * @param string[] $month_names
326
	 * @param string[] $month_names_short
327
	 * @param integer  $max_days_in_month
328
	 * @param string   $calendar_name
329
	 * @param string   $calendar_symbol
330
	 *
331
	 * @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...
332
	 */
333
	private static function calInfoCalendar($month_names, $month_names_short, $max_days_in_month, $calendar_name, $calendar_symbol) {
334
		return array(
335
			'months'         => array_slice($month_names, 1, null, true),
336
			'abbrevmonths'   => array_slice($month_names_short, 1, null, true),
337
			'maxdaysinmonth' => $max_days_in_month,
338
			'calname'        => $calendar_name,
339
			'calsymbol'      => $calendar_symbol,
340
		);
341
	}
342
343
	/**
344
	 *  Converts from a supported calendar to Julian Day Count
345
	 *
346
	 * Shim implementation of cal_to_jd()
347
	 *
348
	 * @link https://php.net/cal_to_jd
349
	 *
350
	 * @param integer $calendar_id
351
	 * @param integer $month
352
	 * @param integer $day
353
	 * @param integer $year
354
	 *
355
	 * @return integer|boolean
356
	 */
357
	public static function calToJd($calendar_id, $month, $day, $year) {
358
		switch ($calendar_id) {
359
		case CAL_FRENCH:
360
			return self::frenchToJd($month, $day, $year);
361
362
		case CAL_GREGORIAN:
363
			return self::gregorianToJd($month, $day, $year);
364
365
		case CAL_JEWISH:
366
			return self::jewishToJd($month, $day, $year);
367
368
		case CAL_JULIAN:
369
			return self::julianToJd($month, $day, $year);
370
371
		default:
372
			return trigger_error('invalid calendar ID ' . $calendar_id . '.', E_USER_WARNING);
373
		}
374
	}
375
376
	/**
377
	 * Get Unix timestamp for midnight on Easter of a given year.
378
	 *
379
	 * Shim implementation of easter_date()
380
	 *
381
	 * @link https://php.net/easter_date
382
	 *
383
	 * @param integer $year
384
	 *
385
	 * @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...
386
	 */
387
	public static function easterDate($year) {
388
		if ($year < 1970 || $year > 2037) {
389
			return trigger_error('This function is only valid for years between 1970 and 2037 inclusive', E_USER_WARNING);
390
		}
391
392
		$days = self::$gregorian_calendar->easterDays($year);
393
394
		// Calculate time-zone offset
395
		$date_time      = new \DateTime('now', new \DateTimeZone(date_default_timezone_get()));
396
		$offset_seconds = (int) $date_time->format('Z');
397
398
		if ($days < 11) {
399
			return self::jdtounix(self::$gregorian_calendar->ymdToJd($year, 3, $days + 21)) - $offset_seconds;
400
		} else {
401
			return self::jdtounix(self::$gregorian_calendar->ymdToJd($year, 4, $days - 10)) - $offset_seconds;
402
		}
403
	}
404
405
	/**
406
	 * Get number of days after March 21 on which Easter falls for a given year.
407
	 *
408
	 * Shim implementation of easter_days()
409
	 *
410
	 * @link https://php.net/easter_days
411
	 *
412
	 * @param integer $year
413
	 * @param integer $method Use the Julian or Gregorian calendar
414
	 *
415
	 * @return integer
416
	 */
417
	public static function easterDays($year, $method) {
418
		if (
419
			$method == CAL_EASTER_ALWAYS_JULIAN ||
420
			$method == CAL_EASTER_ROMAN && $year <= 1582 ||
421
			$year <= 1752 && $method != CAL_EASTER_ROMAN && $method != CAL_EASTER_ALWAYS_GREGORIAN
422
		) {
423
			return self::$julian_calendar->easterDays($year);
424
		} else {
425
			return self::$gregorian_calendar->easterDays($year);
426
		}
427
	}
428
429
	/**
430
	 * Converts a date from the French Republican Calendar to a Julian Day Count.
431
	 *
432
	 * Shim implementation of FrenchToJD()
433
	 *
434
	 * @link https://php.net/FrenchToJD
435
	 *
436
	 * @param integer $month
437
	 * @param integer $day
438
	 * @param integer $year
439
	 *
440
	 * @return integer
441
	 */
442
	public static function frenchToJd($month, $day, $year) {
443
		if ($year <= 0) {
444
			return 0;
445
		} else {
446
			return self::$french_calendar->ymdToJd($year, $month, $day);
447
		}
448
	}
449
450
	/**
451
	 * Converts a Gregorian date to Julian Day Count.
452
	 *
453
	 * Shim implementation of GregorianToJD()
454
	 *
455
	 * @link https://php.net/GregorianToJD
456
	 *
457
	 * @param integer $month
458
	 * @param integer $day
459
	 * @param integer $year
460
	 *
461
	 * @return integer
462
	 */
463
	public static function gregorianToJd($month, $day, $year) {
464
		if ($year == 0) {
465
			return 0;
466
		} else {
467
			return self::$gregorian_calendar->ymdToJd($year, $month, $day);
468
		}
469
	}
470
471
	/**
472
	 * Returns the day of the week.
473
	 *
474
	 * Shim implementation of JDDayOfWeek()
475
	 *
476
	 * @link https://php.net/JDDayOfWeek
477
	 * @link https://bugs.php.net/bug.php?id=67960
478
	 *
479
	 * @param integer $julian_day
480
	 * @param integer $mode
481
	 *
482
	 * @return integer|string
483
	 */
484
	public static function jdDayOfWeek($julian_day, $mode) {
485
		$day_of_week = ($julian_day + 1) % 7;
486
		if ($day_of_week < 0) {
487
			$day_of_week += 7;
488
		}
489
490
		switch ($mode) {
491
		case 1: // 1, not CAL_DOW_LONG - see bug 67960
492
			return self::$DAY_NAMES[$day_of_week];
493
494
		case 2: // 2, not CAL_DOW_SHORT - see bug 67960
495
			return self::$DAY_NAMES_SHORT[$day_of_week];
496
497
		default: // CAL_DOW_DAYNO or anything else
498
			return $day_of_week;
499
		}
500
	}
501
502
	/**
503
	 * Returns a month name.
504
	 *
505
	 * Shim implementation of JDMonthName()
506
	 *
507
	 * @link https://php.net/JDMonthName
508
	 *
509
	 * @param integer $julian_day
510
	 * @param integer $mode
511
	 *
512
	 * @return string
513
	 */
514
	public static function jdMonthName($julian_day, $mode) {
515
		switch ($mode) {
516
		case CAL_MONTH_GREGORIAN_LONG:
517
			return self::jdMonthNameCalendar(self::$gregorian_calendar, $julian_day, self::$MONTH_NAMES);
518
519
		case CAL_MONTH_JULIAN_LONG:
520
			return self::jdMonthNameCalendar(self::$julian_calendar, $julian_day, self::$MONTH_NAMES);
521
522
		case CAL_MONTH_JULIAN_SHORT:
523
			return self::jdMonthNameCalendar(self::$julian_calendar, $julian_day, self::$MONTH_NAMES_SHORT);
524
525
		case CAL_MONTH_JEWISH:
526
			return self::jdMonthNameCalendar(self::$jewish_calendar, $julian_day, self::jdMonthNameJewishMonths($julian_day));
527
528
		case CAL_MONTH_FRENCH:
529
			return self::jdMonthNameCalendar(self::$french_calendar, $julian_day, self::$MONTH_NAMES_FRENCH);
530
531
		case CAL_MONTH_GREGORIAN_SHORT:
532
		default:
533
			return self::jdMonthNameCalendar(self::$gregorian_calendar, $julian_day, self::$MONTH_NAMES_SHORT);
534
		}
535
	}
536
537
	/**
538
	 * Calculate the month-name for a given julian day, in a given calendar,
539
	 * with given set of month names.
540
	 *
541
	 * @param CalendarInterface $calendar
542
	 * @param integer           $julian_day
543
	 * @param string[]          $months
544
	 *
545
	 * @return string
546
	 */
547
	private static function jdMonthNameCalendar(CalendarInterface $calendar, $julian_day, $months) {
548
		list(, $month) = $calendar->jdToYmd($julian_day);
549
550
		return $months[$month];
551
	}
552
553
	/**
554
	 * Determine which month names to use for the Jewish calendar.
555
	 *
556
	 * @param integer $julian_day
557
	 *
558
	 * @return string[]
559
	 */
560
	private static function jdMonthNameJewishMonths($julian_day) {
561
		list(, , $year) = explode('/', self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846));
562
563
		if (self::$jewish_calendar->isLeapYear($year)) {
564
			return self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH_LEAP_YEAR;
565
		} else {
566
			return self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH;
567
		}
568
	}
569
570
	/**
571
	 * Convert a Julian day in a specific calendar to a day/month/year.
572
	 *
573
	 * Julian days outside the specified range are returned as “0/0/0”.
574
	 *
575
	 * @param CalendarInterface $calendar
576
	 * @param integer           $julian_day
577
	 * @param integer           $min_jd
578
	 * @param integer           $max_jd
579
	 *
580
	 * @return string
581
	 */
582
	private static function jdToCalendar(CalendarInterface $calendar, $julian_day, $min_jd, $max_jd) {
583
		if ($julian_day >= $min_jd && $julian_day <= $max_jd) {
584
			list($year, $month, $day) = $calendar->jdToYmd($julian_day);
585
586
			return $month . '/' . $day . '/' . $year;
587
		} else {
588
			return '0/0/0';
589
		}
590
	}
591
592
	/**
593
	 * Converts a Julian Day Count to the French Republican Calendar.
594
	 *
595
	 * Shim implementation of JDToFrench()
596
	 *
597
	 * @link https://php.net/JDToFrench
598
	 *
599
	 * @param integer $julian_day A Julian Day number
600
	 *
601
	 * @return string A string of the form "month/day/year"
602
	 */
603
	public static function jdToFrench($julian_day) {
604
		// JDToFrench() converts years 1 to 14 inclusive, even though the calendar
605
		// officially ended on 10 Nivôse 14 (JD 2380687, 31st December 1805 Gregorian).
606
		return self::jdToCalendar(self::$french_calendar, $julian_day, 2375840, 2380952);
607
	}
608
609
	/**
610
	 * Converts Julian Day Count to Gregorian date.
611
	 *
612
	 * Shim implementation of JDToGregorian()
613
	 *
614
	 * @link https://php.net/JDToGregorian
615
	 *
616
	 * @param integer $julian_day A Julian Day number
617
	 *
618
	 * @return string A string of the form "month/day/year"
619
	 */
620
	public static function jdToGregorian($julian_day) {
621
		// PHP has different limits on 32 and 64 bit systems.
622
		$MAX_JD = PHP_INT_SIZE == 4 ? 536838866 : 2305843009213661906;
623
624
		return self::jdToCalendar(self::$gregorian_calendar, $julian_day, 1, $MAX_JD);
625
	}
626
627
	/**
628
	 * Converts a Julian day count to a Jewish calendar date.
629
	 *
630
	 * Shim implementation of JdtoJjewish()
631
	 *
632
	 * @link https://php.net/JdtoJewish
633
	 *
634
	 * @param integer $julian_day A Julian Day number
635
	 * @param boolean $hebrew     If true, the date is returned in Hebrew text
636
	 * @param integer $fl         If $hebrew is true, then add alafim and gereshayim to the text
637
	 *
638
	 * @return string|boolean A string of the form "month/day/year", or false on error
639
	 */
640
	public static function jdToJewish($julian_day, $hebrew, $fl) {
641
		if ($hebrew) {
642
			if ($julian_day < 347998 || $julian_day > 4000075) {
643
				return trigger_error('Year out of range (0-9999).', E_USER_WARNING);
644
			}
645
646
			return self::$jewish_calendar->jdToHebrew(
647
				$julian_day,
648
				(bool)($fl & CAL_JEWISH_ADD_ALAFIM_GERESH),
649
				(bool)($fl & CAL_JEWISH_ADD_ALAFIM),
650
				(bool)($fl & CAL_JEWISH_ADD_GERESHAYIM)
651
			);
652
		} else {
653
			// The upper limit is hard-coded into PHP to prevent numeric overflow on 32 bit systems.
654
			return self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846);
655
		}
656
	}
657
658
	/**
659
	 * Converts a Julian Day Count to a Julian Calendar Date.
660
	 *
661
	 * Shim implementation of JDToJulian()
662
	 *
663
	 * @link https://php.net/JDToJulian
664
	 *
665
	 * @param integer $julian_day A Julian Day number
666
	 *
667
	 * @return string A string of the form "month/day/year"
668
	 */
669
	public static function jdToJulian($julian_day) {
670
		// PHP has different limits on 32 and 64 bit systems.
671
		$MAX_JD = PHP_INT_SIZE == 4 ? 536838829 : 784368370349;
672
673
		return self::jdToCalendar(self::$julian_calendar, $julian_day, 1, $MAX_JD);
674
	}
675
676
	/**
677
	 * Convert Julian Day to Unix timestamp.
678
	 *
679
	 * Shim implementation of jdtounix()
680
	 *
681
	 * @link https://php.net/jdtounix
682
	 *
683
	 * @param integer $julian_day
684
	 *
685
	 * @return integer|false
686
	 */
687
	public static function jdToUnix($julian_day) {
688
		if ($julian_day >= 2440588 && $julian_day <= 2465343) {
689
			return (int) ($julian_day - 2440588) * 86400;
690
		} else {
691
			return false;
692
		}
693
	}
694
695
	/**
696
	 * Converts a date in the Jewish Calendar to Julian Day Count.
697
	 *
698
	 * Shim implementation of JewishToJD()
699
	 *
700
	 * @link https://php.net/JewishToJD
701
	 *
702
	 * @param integer $month
703
	 * @param integer $day
704
	 * @param integer $year
705
	 *
706
	 * @return integer
707
	 */
708
	public static function jewishToJd($month, $day, $year) {
709
		if ($year <= 0) {
710
			return 0;
711
		} else {
712
			return self::$jewish_calendar->ymdToJd($year, $month, $day);
713
		}
714
	}
715
716
	/**
717
	 * Converts a Julian Calendar date to Julian Day Count.
718
	 *
719
	 * Shim implementation of JdToJulian()
720
	 *
721
	 * @link https://php.net/JdToJulian
722
	 *
723
	 * @param integer $month
724
	 * @param integer $day
725
	 * @param integer $year
726
	 *
727
	 * @return integer
728
	 */
729
	public static function julianToJd($month, $day, $year) {
730
		if ($year == 0) {
731
			return 0;
732
		} else {
733
			return self::$julian_calendar->ymdToJd($year, $month, $day);
734
		}
735
	}
736
737
	/**
738
	 * Convert Unix timestamp to Julian Day.
739
	 *
740
	 * Shim implementation of unixtojd()
741
	 *
742
	 * @link https://php.net/unixtojd
743
	 *
744
	 * @param integer $timestamp
745
	 *
746
	 * @return false|integer
747
	 */
748
	public static function unixToJd($timestamp) {
749
		if ($timestamp < 0) {
750
			return false;
751
		} else {
752
			// Convert timestamp based on local timezone
753
			return self::GregorianToJd(gmdate('n', $timestamp), gmdate('j', $timestamp), gmdate('Y', $timestamp));
754
		}
755
	}
756
}
757