Passed
Push — master ( 179a7a...c74ab7 )
by Yang
07:06 queued 54s
created

IDCard   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 35
lcom 1
cbo 0
dl 0
loc 235
ccs 68
cts 68
cp 1
rs 9
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A checkAreaCode() 0 6 1
A checkBirthday() 0 8 1
A checkCode() 0 12 2
A address() 0 4 2
A province() 0 6 2
A city() 0 6 2
A zone() 0 6 2
A birthday() 0 4 1
A year() 0 4 1
A month() 0 4 1
A day() 0 4 1
A check() 0 4 3
B age() 0 20 6
A sex() 0 4 3
A constellation() 0 14 4
A zodiac() 0 7 2
1
<?php
2
3
namespace Leonis\IDCard;
4
5
class IDCard
6
{
7
    /**
8
     * 身份证号.
9
     *
10
     * @var string
11
     */
12
    protected $id;
13
14
    /**
15
     * 行政区划代码
16
     *
17
     * @var array
18
     */
19
    protected $areaCodes;
20
21 16
    public function __construct(string $id)
22
    {
23 16
        $this->id = strtoupper($id);
24 16
        $this->areaCodes = (array) require __DIR__.'/../data/codes.php';
25 16
    }
26
27
    /**
28
     * 验证身份号.
29
     *
30
     * @return bool
31
     */
32 9
    public function check()
33
    {
34 9
        return $this->checkAreaCode() && $this->checkBirthday() && $this->checkCode();
35
    }
36
37
    /**
38
     * 验证行政区划代码
39
     *
40
     * @return bool
41
     */
42 10
    public function checkAreaCode()
43
    {
44 10
        $areaCode = substr($this->id, 0, 6);
45
46 10
        return array_key_exists($areaCode, $this->areaCodes);
47
    }
48
49
    /**
50
     * 验证生日.
51
     *
52
     * @return bool
53
     */
54 10
    public function checkBirthday()
55
    {
56 10
        $year = substr($this->id, 6, 4);
57 10
        $month = substr($this->id, 10, 2);
58 10
        $day = substr($this->id, 12, 2);
59
60 10
        return checkdate($month, $day, $year);
61
    }
62
63
    /**
64
     * 验证校验码
65
     *
66
     * @return bool
67
     */
68 10
    public function checkCode()
69
    {
70 10
        $weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
71 10
        $codes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
72 10
        $code = substr($this->id, 17, 1);
73 10
        $sum = 0;
74 10
        for ($i = 0; $i < 17; $i++) {
75 10
            $sum += substr(substr($this->id, 0, 17), $i, 1) * $weight[$i];
76
        }
77
78 10
        return $code == $codes[$sum % 11];
79
    }
80
81
    /**
82
     * 获取地址
83
     *
84
     * @param string $separator
85
     *
86
     * @return bool|string
87
     */
88 1
    public function address(string $separator = '')
89
    {
90 1
        return $this->check() ? $this->province().$separator.$this->city().$separator.$this->zone() : false;
91
    }
92
93
    /**
94
     * 获取省
95
     *
96
     * @return bool|mixed
97
     */
98 2
    public function province()
99
    {
100 2
        $provinceCode = substr($this->id, 0, 2).'0000';
101
102 2
        return $this->check() ? $this->areaCodes[$provinceCode] : false;
103
    }
104
105
    /**
106
     * 获取市
107
     *
108
     * @return bool|mixed
109
     */
110 2
    public function city()
111
    {
112 2
        $cityCode = substr($this->id, 0, 4).'00';
113
114 2
        return $this->check() ? $this->areaCodes[$cityCode] : false;
115
    }
116
117
    /**
118
     * 获取区.
119
     *
120
     * @return bool|mixed
121
     */
122 2
    public function zone()
123
    {
124 2
        $areaCode = substr($this->id, 0, 6);
125
126 2
        return $this->check() ? $this->areaCodes[$areaCode] : false;
127
    }
128
129
    /**
130
     * 获取生日.
131
     *
132
     * @param string $format
133
     *
134
     * @return false|string
135
     */
136 1
    public function birthday(string $format)
137
    {
138 1
        return date($format, strtotime($this->year().'-'.$this->month().'-'.$this->day()));
139
    }
140
141
    /**
142
     * 获取年.
143
     *
144
     * @return int
145
     */
146 4
    public function year()
147
    {
148 4
        return (int) substr($this->id, 6, 4);
149
    }
150
151
    /**
152
     * 获取月.
153
     *
154
     * @return int
155
     */
156 4
    public function month()
157
    {
158 4
        return (int) substr($this->id, 10, 2);
159
    }
160
161
    /**
162
     * 获取日.
163
     *
164
     * @return int
165
     */
166 4
    public function day()
167
    {
168 4
        return (int) substr($this->id, 12, 2);
169
    }
170
171
    /**
172
     * 获取年龄.
173
     *
174
     * @return bool|int
175
     */
176 1
    public function age()
177
    {
178 1
        $year = $this->year();
179 1
        $month = $this->month();
180 1
        $day = $this->day();
181
182 1
        $nowYear = (int) date('Y');
183 1
        $nowMonth = (int) date('n');
184 1
        $nowDay = (int) date('j');
185
186 1
        $age = 0;
187 1
        if ($nowYear > $year) {
188 1
            $age = $nowYear - $year - 1;
189
        }
190 1
        if ($nowMonth > $month || ($nowMonth === $month && $nowDay >= $day)) {
191 1
            $age++;
192
        }
193
194 1
        return $this->check() ? $age : false;
195
    }
196
197
    /**
198
     * 获取性别.
199
     *
200
     * @return bool|string
201
     */
202 1
    public function sex()
203
    {
204 1
        return $this->check() ? substr($this->id, 16, 1) % 2 ? '男' : '女' : false;
205
    }
206
207
    /**
208
     * 获取星座.
209
     *
210
     * @return bool|mixed
211
     */
212 1
    public function constellation()
213
    {
214 1
        $constellation = ['水瓶座', '双鱼座', '白羊座', '金牛座', '双子座', '巨蟹座', '狮子座', '处女座', '天秤座', '天蝎座', '射手座', '魔羯座'];
215 1
        $constellationDays = [21, 20, 21, 20, 21, 22, 23, 23, 23, 24, 22, 21];
216
217 1
        $month = $this->month() - 1;
218 1
        $day = $this->day();
219
220 1
        if ($day < $constellationDays[$month]) {
221 1
            $month--;
222
        }
223
224 1
        return $this->check() ? $month >= 0 ? $constellation[$month] : $constellation[11] : false;
225
    }
226
227
    /**
228
     * 获取属相.
229
     *
230
     * @return bool|string
231
     */
232 1
    public function zodiac()
233
    {
234 1
        $zodiac = ['牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪', '鼠'];
235 1
        $index = abs($this->year() - 1901) % 12;
236
237 1
        return $this->check() ? $zodiac[$index] : false;
238
    }
239
}
240