Completed
Push — develop ( 427cfd...9c56e1 )
by Greg
01:56
created

Shim::jdMonthName()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 15
c 1
b 0
f 0
nc 7
nop 2
dl 0
loc 22
rs 6.9811
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 bool
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 bool
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 bool
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.10', '<') ;
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 int $calendar_id
162
	 * @param int $month
163
	 * @param int $year
164
	 *
165
	 * @return int|bool 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 int               $year
191
	 * @param int               $month
192
	 *
193
	 * @return int|bool
194
	 */
195
	private static function calDaysInMonthCalendar(CalendarInterface $calendar, $year, $month) {
196
		try {
197
			return $calendar->daysInMonth($year, $month);
198
		} catch (InvalidArgumentException $ex) {
199
			$error_msg = PHP_VERSION_ID < 70200 ? 'invalid date.' : 'invalid date';
200
201
			return trigger_error($error_msg, E_USER_WARNING);
202
		}
203
	}
204
205
	/**
206
	 * Calculate the number of days in a month in the French calendar.
207
	 *
208
	 * Mimic PHP’s validation of the parameters
209
	 *
210
	 * @param int $year
211
	 * @param int $month
212
	 *
213
	 * @return int|bool
214
	 */
215
	private static function calDaysInMonthFrench($year, $month) {
216
		if ($month == 13 && $year == 14 && self::shouldEmulateBug67976()) {
217
			return -2380948;
218 View Code Duplication
		} elseif ($year > 14) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
219
			$error_msg = PHP_VERSION_ID < 70200 ? 'invalid date.' : 'invalid date';
220
221
			return trigger_error($error_msg, E_USER_WARNING);
222
		} else {
223
			return self::calDaysInMonthCalendar(self::$french_calendar, $year, $month);
224
		}
225
	}
226
227
	/**
228
	 * Converts from Julian Day Count to a supported calendar.
229
	 *
230
	 * Shim implementation of cal_from_jd()
231
	 *
232
	 * @link https://php.net/cal_from_jd
233
	 *
234
	 * @param int $julian_day  Julian Day number
235
	 * @param int $calendar_id Calendar constant
236
	 *
237
	 * @return array|bool
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array|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...
238
	 */
239
	public static function calFromJd($julian_day, $calendar_id) {
240
		switch ($calendar_id) {
241
		case CAL_FRENCH:
242
			return self::calFromJdCalendar($julian_day, self::jdToFrench($julian_day), self::$MONTH_NAMES_FRENCH, self::$MONTH_NAMES_FRENCH);
243
244
		case CAL_GREGORIAN:
245
			return self::calFromJdCalendar($julian_day, self::jdToGregorian($julian_day), self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT);
246
247
		case CAL_JEWISH:
248
			$months = self::jdMonthNameJewishMonths($julian_day);
249
250
			$cal = self::calFromJdCalendar($julian_day, self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846), $months, $months);
251
252
			if (($julian_day < 347998 || $julian_day > 324542846) && !self::shouldEmulateBug67976()) {
253
				$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...
254
				$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...
255
				$cal['abbrevdayname'] = '';
256
			}
257
258
			return $cal;
259
260
		case CAL_JULIAN:
261
			return self::calFromJdCalendar($julian_day, self::jdToJulian($julian_day), self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT);
262
263
		default:
264
			return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING);
265
		}
266
	}
267
268
	/**
269
	 * Convert a Julian day number to a calendar and provide details.
270
	 *
271
	 * @param int      $julian_day
272
	 * @param string   $mdy
273
	 * @param string[] $months
274
	 * @param string[] $months_short
275
	 *
276
	 * @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...
277
	 */
278
	private static function calFromJdCalendar($julian_day, $mdy, $months, $months_short) {
279
		list($month, $day, $year) = explode('/', $mdy);
280
281
		return array(
282
			'date'          => $month . '/' . $day . '/' . $year,
283
			'month'         => (int) $month,
284
			'day'           => (int) $day,
285
			'year'          => (int) $year,
286
			'dow'           => self::jdDayOfWeek($julian_day, 0),
287
			'abbrevdayname' => self::jdDayOfWeek($julian_day, 2),
288
			'dayname'       => self::jdDayOfWeek($julian_day, 1),
289
			'abbrevmonth'   => $months_short[$month],
290
			'monthname'     => $months[$month],
291
		);
292
	}
293
294
	/**
295
	 * Returns information about a particular calendar.
296
	 *
297
	 * Shim implementation of cal_info()
298
	 *
299
	 * @link https://php.net/cal_info
300
	 *
301
	 * @param int $calendar_id
302
	 *
303
	 * @return array|bool
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...
304
	 */
305
	public static function calInfo($calendar_id) {
306
		switch ($calendar_id) {
307
		case CAL_FRENCH:
308
			return self::calInfoCalendar(self::$MONTH_NAMES_FRENCH, self::$MONTH_NAMES_FRENCH, 30, 'French', 'CAL_FRENCH');
309
310
		case CAL_GREGORIAN:
311
			return self::calInfoCalendar(self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT, 31, 'Gregorian', 'CAL_GREGORIAN');
312
313
		case CAL_JEWISH:
314
			$months = self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH_LEAP_YEAR;
315
316
			return self::calInfoCalendar($months, $months, 30, 'Jewish', 'CAL_JEWISH');
317
318
		case CAL_JULIAN:
319
			return self::calInfoCalendar(self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT, 31, 'Julian', 'CAL_JULIAN');
320
321
		case -1:
322
			return array(
323
				CAL_GREGORIAN => self::calInfo(CAL_GREGORIAN),
324
				CAL_JULIAN    => self::calInfo(CAL_JULIAN),
325
				CAL_JEWISH    => self::calInfo(CAL_JEWISH),
326
				CAL_FRENCH    => self::calInfo(CAL_FRENCH),
327
			);
328
329
		default:
330
			return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING);
331
		}
332
	}
333
334
	/**
335
	 * Returns information about the French calendar.
336
	 *
337
	 * @param string[] $month_names
338
	 * @param string[] $month_names_short
339
	 * @param int      $max_days_in_month
340
	 * @param string   $calendar_name
341
	 * @param string   $calendar_symbol
342
	 *
343
	 * @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...
344
	 */
345
	private static function calInfoCalendar($month_names, $month_names_short, $max_days_in_month, $calendar_name, $calendar_symbol) {
346
		return array(
347
			'months'         => array_slice($month_names, 1, null, true),
348
			'abbrevmonths'   => array_slice($month_names_short, 1, null, true),
349
			'maxdaysinmonth' => $max_days_in_month,
350
			'calname'        => $calendar_name,
351
			'calsymbol'      => $calendar_symbol,
352
		);
353
	}
354
355
	/**
356
	 *  Converts from a supported calendar to Julian Day Count
357
	 *
358
	 * Shim implementation of cal_to_jd()
359
	 *
360
	 * @link https://php.net/cal_to_jd
361
	 *
362
	 * @param int $calendar_id
363
	 * @param int $month
364
	 * @param int $day
365
	 * @param int $year
366
	 *
367
	 * @return int|bool
368
	 */
369
	public static function calToJd($calendar_id, $month, $day, $year) {
370
		switch ($calendar_id) {
371
		case CAL_FRENCH:
372
			return self::frenchToJd($month, $day, $year);
373
374
		case CAL_GREGORIAN:
375
			return self::gregorianToJd($month, $day, $year);
376
377
		case CAL_JEWISH:
378
			return self::jewishToJd($month, $day, $year);
379
380
		case CAL_JULIAN:
381
			return self::julianToJd($month, $day, $year);
382
383
		default:
384
			return trigger_error('invalid calendar ID ' . $calendar_id . '.', E_USER_WARNING);
385
		}
386
	}
387
388
	/**
389
	 * Get Unix timestamp for midnight on Easter of a given year.
390
	 *
391
	 * Shim implementation of easter_date()
392
	 *
393
	 * @link https://php.net/easter_date
394
	 *
395
	 * @param int $year
396
	 *
397
	 * @return int|bool
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...
398
	 */
399
	public static function easterDate($year) {
400
		if ($year < 1970 || $year > 2037) {
401
			return trigger_error('This function is only valid for years between 1970 and 2037 inclusive', E_USER_WARNING);
402
		}
403
404
		$days = self::$gregorian_calendar->easterDays($year);
405
406
		// Calculate time-zone offset
407
		$date_time      = new \DateTime('now', new \DateTimeZone(date_default_timezone_get()));
408
		$offset_seconds = (int) $date_time->format('Z');
409
410
		if ($days < 11) {
411
			return self::jdtounix(self::$gregorian_calendar->ymdToJd($year, 3, $days + 21)) - $offset_seconds;
412
		} else {
413
			return self::jdtounix(self::$gregorian_calendar->ymdToJd($year, 4, $days - 10)) - $offset_seconds;
414
		}
415
	}
416
417
	/**
418
	 * Get number of days after March 21 on which Easter falls for a given year.
419
	 *
420
	 * Shim implementation of easter_days()
421
	 *
422
	 * @link https://php.net/easter_days
423
	 *
424
	 * @param int $year
425
	 * @param int $method Use the Julian or Gregorian calendar
426
	 *
427
	 * @return int
428
	 */
429
	public static function easterDays($year, $method) {
430
		if (
431
			$method == CAL_EASTER_ALWAYS_JULIAN ||
432
			$method == CAL_EASTER_ROMAN && $year <= 1582 ||
433
			$year <= 1752 && $method != CAL_EASTER_ROMAN && $method != CAL_EASTER_ALWAYS_GREGORIAN
434
		) {
435
			return self::$julian_calendar->easterDays($year);
436
		} else {
437
			return self::$gregorian_calendar->easterDays($year);
438
		}
439
	}
440
441
	/**
442
	 * Converts a date from the French Republican Calendar to a Julian Day Count.
443
	 *
444
	 * Shim implementation of FrenchToJD()
445
	 *
446
	 * @link https://php.net/FrenchToJD
447
	 *
448
	 * @param int $month
449
	 * @param int $day
450
	 * @param int $year
451
	 *
452
	 * @return int
453
	 */
454
	public static function frenchToJd($month, $day, $year) {
455
		if ($year <= 0) {
456
			return 0;
457
		} else {
458
			return self::$french_calendar->ymdToJd($year, $month, $day);
459
		}
460
	}
461
462
	/**
463
	 * Converts a Gregorian date to Julian Day Count.
464
	 *
465
	 * Shim implementation of GregorianToJD()
466
	 *
467
	 * @link https://php.net/GregorianToJD
468
	 *
469
	 * @param int $month
470
	 * @param int $day
471
	 * @param int $year
472
	 *
473
	 * @return int
474
	 */
475
	public static function gregorianToJd($month, $day, $year) {
476
		if ($year == 0) {
477
			return 0;
478
		} else {
479
			return self::$gregorian_calendar->ymdToJd($year, $month, $day);
480
		}
481
	}
482
483
	/**
484
	 * Returns the day of the week.
485
	 *
486
	 * Shim implementation of JDDayOfWeek()
487
	 *
488
	 * @link https://php.net/JDDayOfWeek
489
	 * @link https://bugs.php.net/bug.php?id=67960
490
	 *
491
	 * @param int $julian_day
492
	 * @param int $mode
493
	 *
494
	 * @return int|string
495
	 */
496
	public static function jdDayOfWeek($julian_day, $mode) {
497
		$day_of_week = ($julian_day + 1) % 7;
498
		if ($day_of_week < 0) {
499
			$day_of_week += 7;
500
		}
501
502
		switch ($mode) {
503
		case 1: // 1, not CAL_DOW_LONG - see bug 67960
504
			return self::$DAY_NAMES[$day_of_week];
505
506
		case 2: // 2, not CAL_DOW_SHORT - see bug 67960
507
			return self::$DAY_NAMES_SHORT[$day_of_week];
508
509
		default: // CAL_DOW_DAYNO or anything else
510
			return $day_of_week;
511
		}
512
	}
513
514
	/**
515
	 * Returns a month name.
516
	 *
517
	 * Shim implementation of JDMonthName()
518
	 *
519
	 * @link https://php.net/JDMonthName
520
	 *
521
	 * @param int $julian_day
522
	 * @param int $mode
523
	 *
524
	 * @return string
525
	 */
526
	public static function jdMonthName($julian_day, $mode) {
527
		switch ($mode) {
528
		case CAL_MONTH_GREGORIAN_LONG:
529
			return self::jdMonthNameCalendar(self::$gregorian_calendar, $julian_day, self::$MONTH_NAMES);
530
531
		case CAL_MONTH_JULIAN_LONG:
532
			return self::jdMonthNameCalendar(self::$julian_calendar, $julian_day, self::$MONTH_NAMES);
533
534
		case CAL_MONTH_JULIAN_SHORT:
535
			return self::jdMonthNameCalendar(self::$julian_calendar, $julian_day, self::$MONTH_NAMES_SHORT);
536
537
		case CAL_MONTH_JEWISH:
538
			return self::jdMonthNameCalendar(self::$jewish_calendar, $julian_day, self::jdMonthNameJewishMonths($julian_day));
539
540
		case CAL_MONTH_FRENCH:
541
			return self::jdMonthNameCalendar(self::$french_calendar, $julian_day, self::$MONTH_NAMES_FRENCH);
542
543
		case CAL_MONTH_GREGORIAN_SHORT:
544
		default:
545
			return self::jdMonthNameCalendar(self::$gregorian_calendar, $julian_day, self::$MONTH_NAMES_SHORT);
546
		}
547
	}
548
549
	/**
550
	 * Calculate the month-name for a given julian day, in a given calendar,
551
	 * with given set of month names.
552
	 *
553
	 * @param CalendarInterface $calendar
554
	 * @param int               $julian_day
555
	 * @param string[]          $months
556
	 *
557
	 * @return string
558
	 */
559
	private static function jdMonthNameCalendar(CalendarInterface $calendar, $julian_day, $months) {
560
		list(, $month) = $calendar->jdToYmd($julian_day);
561
562
		return $months[$month];
563
	}
564
565
	/**
566
	 * Determine which month names to use for the Jewish calendar.
567
	 *
568
	 * @param int $julian_day
569
	 *
570
	 * @return string[]
571
	 */
572
	private static function jdMonthNameJewishMonths($julian_day) {
573
		list(, , $year) = explode('/', self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846));
574
575
		if (self::$jewish_calendar->isLeapYear($year)) {
576
			return self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH_LEAP_YEAR;
577
		} else {
578
			return self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH;
579
		}
580
	}
581
582
	/**
583
	 * Convert a Julian day in a specific calendar to a day/month/year.
584
	 *
585
	 * Julian days outside the specified range are returned as “0/0/0”.
586
	 *
587
	 * @param CalendarInterface $calendar
588
	 * @param int               $julian_day
589
	 * @param int               $min_jd
590
	 * @param int               $max_jd
591
	 *
592
	 * @return string
593
	 */
594
	private static function jdToCalendar(CalendarInterface $calendar, $julian_day, $min_jd, $max_jd) {
595
		if ($julian_day >= $min_jd && $julian_day <= $max_jd) {
596
			list($year, $month, $day) = $calendar->jdToYmd($julian_day);
597
598
			return $month . '/' . $day . '/' . $year;
599
		} else {
600
			return '0/0/0';
601
		}
602
	}
603
604
	/**
605
	 * Converts a Julian Day Count to the French Republican Calendar.
606
	 *
607
	 * Shim implementation of JDToFrench()
608
	 *
609
	 * @link https://php.net/JDToFrench
610
	 *
611
	 * @param int $julian_day A Julian Day number
612
	 *
613
	 * @return string A string of the form "month/day/year"
614
	 */
615
	public static function jdToFrench($julian_day) {
616
		// JDToFrench() converts years 1 to 14 inclusive, even though the calendar
617
		// officially ended on 10 Nivôse 14 (JD 2380687, 31st December 1805 Gregorian).
618
		return self::jdToCalendar(self::$french_calendar, $julian_day, 2375840, 2380952);
619
	}
620
621
	/**
622
	 * Converts Julian Day Count to Gregorian date.
623
	 *
624
	 * Shim implementation of JDToGregorian()
625
	 *
626
	 * @link https://php.net/JDToGregorian
627
	 *
628
	 * @param int $julian_day A Julian Day number
629
	 *
630
	 * @return string A string of the form "month/day/year"
631
	 */
632
	public static function jdToGregorian($julian_day) {
633
		// PHP has different limits on 32 and 64 bit systems.
634
		$MAX_JD = PHP_INT_SIZE == 4 ? 536838866 : 2305843009213661906;
635
636
		return self::jdToCalendar(self::$gregorian_calendar, $julian_day, 1, $MAX_JD);
637
	}
638
639
	/**
640
	 * Converts a Julian day count to a Jewish calendar date.
641
	 *
642
	 * Shim implementation of JdtoJjewish()
643
	 *
644
	 * @link https://php.net/JdtoJewish
645
	 *
646
	 * @param int  $julian_day A Julian Day number
647
	 * @param bool $hebrew     If true, the date is returned in Hebrew text
648
	 * @param int  $fl         If $hebrew is true, then add alafim and gereshayim to the text
649
	 *
650
	 * @return string|bool A string of the form "month/day/year", or false on error
651
	 */
652
	public static function jdToJewish($julian_day, $hebrew, $fl) {
653
		if ($hebrew) {
654 View Code Duplication
			if ($julian_day < 347998 || $julian_day > 4000075) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
655
				$error_msg = PHP_VERSION_ID < 70200 ? 'Year out of range (0-9999).' : 'Year out of range (0-9999)';
656
657
				return trigger_error($error_msg, E_USER_WARNING);
658
			}
659
660
			return self::$jewish_calendar->jdToHebrew(
661
				$julian_day,
662
				(bool)($fl & CAL_JEWISH_ADD_ALAFIM_GERESH),
663
				(bool)($fl & CAL_JEWISH_ADD_ALAFIM),
664
				(bool)($fl & CAL_JEWISH_ADD_GERESHAYIM)
665
			);
666
		} else {
667
			// The upper limit is hard-coded into PHP to prevent numeric overflow on 32 bit systems.
668
			return self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846);
669
		}
670
	}
671
672
	/**
673
	 * Converts a Julian Day Count to a Julian Calendar Date.
674
	 *
675
	 * Shim implementation of JDToJulian()
676
	 *
677
	 * @link https://php.net/JDToJulian
678
	 *
679
	 * @param int $julian_day A Julian Day number
680
	 *
681
	 * @return string A string of the form "month/day/year"
682
	 */
683
	public static function jdToJulian($julian_day) {
684
		// PHP has different limits on 32 and 64 bit systems.
685
		$MAX_JD = PHP_INT_SIZE == 4 ? 536838829 : 784368370349;
686
687
		return self::jdToCalendar(self::$julian_calendar, $julian_day, 1, $MAX_JD);
688
	}
689
690
	/**
691
	 * Convert Julian Day to Unix timestamp.
692
	 *
693
	 * Shim implementation of jdtounix()
694
	 *
695
	 * @link https://php.net/jdtounix
696
	 *
697
	 * @param int $julian_day
698
	 *
699
	 * @return int|false
700
	 */
701
	public static function jdToUnix($julian_day) {
702
		if ($julian_day >= 2440588 && $julian_day <= 2465343) {
703
			return (int) ($julian_day - 2440588) * 86400;
704
		} else {
705
			return false;
706
		}
707
	}
708
709
	/**
710
	 * Converts a date in the Jewish Calendar to Julian Day Count.
711
	 *
712
	 * Shim implementation of JewishToJD()
713
	 *
714
	 * @link https://php.net/JewishToJD
715
	 *
716
	 * @param int $month
717
	 * @param int $day
718
	 * @param int $year
719
	 *
720
	 * @return int
721
	 */
722
	public static function jewishToJd($month, $day, $year) {
723
		if ($year <= 0) {
724
			return 0;
725
		} else {
726
			return self::$jewish_calendar->ymdToJd($year, $month, $day);
727
		}
728
	}
729
730
	/**
731
	 * Converts a Julian Calendar date to Julian Day Count.
732
	 *
733
	 * Shim implementation of JdToJulian()
734
	 *
735
	 * @link https://php.net/JdToJulian
736
	 *
737
	 * @param int $month
738
	 * @param int $day
739
	 * @param int $year
740
	 *
741
	 * @return int
742
	 */
743
	public static function julianToJd($month, $day, $year) {
744
		if ($year == 0) {
745
			return 0;
746
		} else {
747
			return self::$julian_calendar->ymdToJd($year, $month, $day);
748
		}
749
	}
750
751
	/**
752
	 * Convert Unix timestamp to Julian Day.
753
	 *
754
	 * Shim implementation of unixtojd()
755
	 *
756
	 * @link https://php.net/unixtojd
757
	 *
758
	 * @param int $timestamp
759
	 *
760
	 * @return false|int
761
	 */
762
	public static function unixToJd($timestamp) {
763
		if ($timestamp < 0) {
764
			return false;
765
		} else {
766
			// Convert timestamp based on local timezone
767
			return self::GregorianToJd(gmdate('n', $timestamp), gmdate('j', $timestamp), gmdate('Y', $timestamp));
768
		}
769
	}
770
}
771