Completed
Push — master ( 078427...b4ca61 )
by Greg
01:49
created

GregorianCalendar::jdEnd()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Fisharebest\ExtCalendar;
3
4
use InvalidArgumentException;
5
6
/**
7
 * class GregorianCalendar - calculations for the (proleptic) Gregorian calendar.
8
 *
9
 * @author    Greg Roach <[email protected]>
10
 * @copyright (c) 2014-2017 Greg Roach
11
 * @license   This program is free software: you can redistribute it and/or modify
12
 *            it under the terms of the GNU General Public License as published by
13
 *            the Free Software Foundation, either version 3 of the License, or
14
 *            (at your option) any later version.
15
 *
16
 *            This program is distributed in the hope that it will be useful,
17
 *            but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 *            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 *            GNU General Public License for more details.
20
 *
21
 *            You should have received a copy of the GNU General Public License
22
 *            along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
class GregorianCalendar extends JulianCalendar implements CalendarInterface {
25
	/**
26
	 * The escape sequence used to indicate this calendar in GEDCOM files.
27
	 *
28
	 * @return string
29
	 */
30
	public function gedcomCalendarEscape() {
31
		return '@#DGREGORIAN@';
32
	}
33
34
	/**
35
	 * @param int $year
36
	 *
37
	 * @return bool
38
	 */
39
	public function isLeapYear($year) {
40
		if ($year < 0) {
41
			$year++;
42
		}
43
44
		return $year % 4 == 0 && $year % 100 != 0 || $year % 400 == 0;
45
	}
46
47
	/**
48
	 * Convert a Julian day number into a year/month/day.
49
	 *
50
	 * @param int $julian_day
51
	 *
52
	 * @return int[]
53
	 */
54
	public function jdToYmd($julian_day) {
55
		$a = $julian_day + 32044;
56
		$b = (int) ((4 * $a + 3) / 146097);
57
		$c = $a - (int) ($b * 146097 / 4);
58
		$d = (int) ((4 * $c + 3) / 1461);
59
		$e = $c - (int) ((1461 * $d) / 4);
60
		$m = (int) ((5 * $e + 2) / 153);
61
62
		$day   = $e - (int) ((153 * $m + 2) / 5) + 1;
63
		$month = $m + 3 - 12 * (int) ($m / 10);
64
		$year  = $b * 100 + $d - 4800 + (int) ($m / 10);
65
		if ($year < 1) {
66
			// 0 is 1 BCE, -1 is 2 BCE, etc.
67
			$year--;
68
		}
69
70
		return array($year, $month, $day);
71
	}
72
73
	/**
74
	 * Convert a year/month/day into a Julian day number
75
	 *
76
	 * @param int $year
77
	 * @param int $month
78
	 * @param int $day
79
	 *
80
	 * @return int
81
	 */
82
	public function ymdToJd($year, $month, $day) {
83 View Code Duplication
		if ($month < 1 || $month > $this->monthsInYear()) {
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...
84
			throw new InvalidArgumentException('Month ' . $month . ' is invalid for this calendar');
85
		}
86
87
		if ($year < 0) {
88
			// 1 BCE is 0, 2 BCE is -1, etc.
89
			++$year;
90
		}
91
		$a     = (int) ((14 - $month) / 12);
92
		$year  = $year + 4800 - $a;
93
		$month = $month + 12 * $a - 3;
94
95
		return $day + (int) ((153 * $month + 2) / 5) + 365 * $year + (int) ($year / 4) - (int) ($year / 100) + (int) ($year / 400) - 32045;
96
	}
97
98
	/**
99
	 * Get the number of days after March 21 that easter falls, for a given year.
100
	 *
101
	 * Uses the algorithm found in PHP’s ext/calendar/easter.c
102
	 *
103
	 * @param int $year
104
	 *
105
	 * @return int
106
	 */
107
	public function easterDays($year) {
108
		// The “golden” number
109
		$golden = $year % 19 + 1;
110
111
		// The “dominical” number (finding a Sunday)
112
		$dom = ($year + (int) ($year / 4) - (int) ($year / 100) + (int) ($year / 400)) % 7;
113
		if ($dom < 0) {
114
			$dom += 7;
115
		}
116
117
		// The solar correction
118
		$solar = (int) (($year - 1600) / 100) - (int) (($year - 1600) / 400);
119
120
		// The lunar correction
121
		$lunar = (int) ((int) (($year - 1400) / 100) * 8) / 25;
122
123
		// The uncorrected “Paschal full moon” date
124
		$pfm = (3 - 11 * $golden + $solar - $lunar) % 30;
125
		if ($pfm < 0) {
126
			$pfm += 30;
127
		}
128
129
		// The corrected “Paschal full moon” date
130
		if ($pfm === 29 || $pfm === 28 && $golden > 11) {
131
			$pfm--;
132
		}
133
134
		$tmp = (4 - $pfm - $dom) % 7;
135
		if ($tmp < 0) {
136
			$tmp += 7;
137
		}
138
139
		return $pfm + $tmp + 1;
140
	}
141
}
142