<?php/** * 身份證工具類 * * @author Tongle Xu <xutongle@gmail.com> 2013-6-6 * @copyright Copyright (c) 2003-2103 tintsoft.com * @license http://www.php100.com * @version $Id$ */class Utils_Idcard {/** * 中國公民社會安全號碼碼最小長度。 */const CHINA_ID_MIN_LENGTH = 15;/** * 中國公民社會安全號碼碼最大長度。 */const CHINA_ID_MAX_LENGTH = 18;/** * 最低年限 */const MIN = 1930;/** * 省、直轄市代碼錶 */public static $cityCode = array ("11","12","13","14","15","21","22","23","31","32","33","34","35","36","37","41","42","43","44","45","46","50","51","52","53","54","61","62","63","64","65","71","81","82","91" );/** * 每位加權因子 */public static $power = array (7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 );/** * 第18位校檢碼 */public static $verifyCode = array ("1","0","X","9","8","7","6","5","4","3","2" );/** * 國內身份證校正 */public static $cityCodes = array ('11' => '北京' );/** * 將15位社會安全號碼碼轉換為18位 * * @param idCard 15位身份編碼 * @return 18位身份編碼 */public static function conver15CardTo18($idCard) {$idCard18 = "";if (strlen ( $idCard ) != self::CHINA_ID_MIN_LENGTH) {return null;}if (self::isNum ( $idCard )) {// 擷取出生年月日$sYear = '19' . substr ( $idCard, 6, 2 );$idCard18 = substr ( $idCard, 0, 6 ) . $sYear . substr ( $idCard, 8 );// 轉換字元數組$iArr = str_split ( $idCard18 );if ($iArr != null) {$iSum17 = self::getPowerSum ( $iArr );// 擷取校正位$sVal = self::getCheckCode18 ( $iSum17 );if (strlen ( $sVal ) > 0) {$idCard18 .= $sVal;} else {return null;}}} else {return null;}return $idCard18;}/** * 驗證身份證是否合法 */public static function validateCard($idCard) {$card = trim ( $idCard );if (self::validateIdCard18 ( $card )) {return true;}if (self::validateIdCard15 ( $card )) {return true;}return false;}/** * 驗證18位身份編碼是否合法 * * @param int $idCard 身份編碼 * @return boolean 是否合法 */public static function validateIdCard18($idCard) {$bTrue = false;if (strlen ( $idCard ) == self::CHINA_ID_MAX_LENGTH) {// 前17位$code17 = substr ( $idCard, 0, 17 );// 第18位$code18 = substr ( $idCard, 17, 1 );if (self::isNum ( $code17 )) {$iArr = str_split ( $code17 );if ($iArr != null) {$iSum17 = self::getPowerSum ( $iArr );// 擷取校正位$val = self::getCheckCode18 ( $iSum17 );if (strlen ( $val ) > 0 && $val == $code18) {$bTrue = true;}}}}return $bTrue;}/** * 驗證15位身份編碼是否合法 * * @param string $idCard 身份編碼 * @return boolean 是否合法 */public static function validateIdCard15($idCard) {if (strlen ( $idCard ) != self::CHINA_ID_MIN_LENGTH) {return false;}if (self::isNum ( $idCard )) {$proCode = substr ( $idCard, 0, 2 );if (! isset ( self::$cityCodes [$proCode] )) {return false;}//升到18位$idCard = self::conver15CardTo18($idCard);return self::validateIdCard18($idCard);} else {return false;}return true;}/** * 根據身份編號擷取年齡 * * @param string idCard 身份編號 * @return 年齡 */public static function getAgeByIdCard($idCard) {$iAge = 0;if (strlen ( $idCard ) == self::CHINA_ID_MIN_LENGTH) {$idCard = self::conver15CardTo18 ( $idCard );}$year = substr ( $idCard, 6, 4 );$iCurrYear = date ( 'Y', time () );$iAge = $iCurrYear - $year;return $iAge;}/** * 根據身份編號擷取生日天 * * @param string $idCard 身份編號 * @return NULL string */public static function getDateByIdCard($idCard) {$len = strlen ( $idCard );if ($len < self::CHINA_ID_MIN_LENGTH) {return null;} else if ($len == CHINA_ID_MIN_LENGTH) {$idCard = self::conver15CardTo18 ( $idCard );}return substr ( $idCard, 12, 2 );}/** * 根據身份編號擷取性別 * * @param string $idCard 身份編號 * @return 性別(M-男,F-女,N-未知) */public static function getGenderByIdCard($idCard) {$sGender = "N";if (strlen ( $idCard ) == self::CHINA_ID_MIN_LENGTH) {$idCard = self::conver15CardTo18 ( $idCard );}$sCardNum = substr ( $idCard, 16, 1 );if (( int ) $sCardNum % 2 != 0) {$sGender = "M";} else {$sGender = "F";}return $sGender;}/** * 根據身份編號擷取戶籍省份 * * @param string $idCard 身份編號 * @return string */public static function getProvinceByIdCard($idCard) {$len = strlen ( $idCard );$sProvince = null;$sProvinNum = "";if ($len == self::CHINA_ID_MIN_LENGTH $len == self::CHINA_ID_MAX_LENGTH) {$sProvinNum = substr ( $idCard, 0, 2 );}$sProvince = self::$cityCodes [$sProvinNum];return $sProvince;}/** * 數字驗證 * * @param int $val */public static function isNum($val) {return $val == null $val == "" ? false : 0 < preg_match ( '/^[0-9]*$/', $val );}/** * 驗證小於當前日期 是否有效 * * @param int $iYear 待驗證日期(年) * @param int $iMonth 待驗證日期(月 1-12) * @param int $iDate 待驗證日期(日) * @return 是否有效 */public static function valiDate($iYear, $iMonth, $iDate) {$year = date ( 'Y', time () );if ($iYear < self::MIN $iYear >= $year) {return false;}if ($iMonth < 1 $iMonth > 12) {return false;}switch ($iMonth) {case 4 :case 6 :case 9 :case 11 :$datePerMonth = 30;break;case 2 :$dm = (($iYear % 4 == 0 && $iYear % 100 != 0) ($iYear % 400 == 0)) && ($iYear > self::MIN && $iYear < $year);$datePerMonth = $dm ? 29 : 28;break;default :$datePerMonth = 31;}return ($iDate >= 1) && ($iDate <= $datePerMonth);}/** * 將身份證的每位和對應位的加權因子相乘之後,再得到和值 * * @param array $iArr * @return 身份證編碼。 */private static function getPowerSum($iArr) {$iSum = 0;$power_len = count ( self::$power );$iarr_len = count ( $iArr );if ($power_len == $iarr_len) {for($i = 0; $i < $iarr_len; $i ++) {for($j = 0; $j < $power_len; $j ++) {if ($i == $j) {$iSum = $iSum + $iArr [$i] * self::$power [$j];}}}}return $iSum;}/** * 將power和值與11模數獲得餘數進行校正碼判斷 * * @param int $iSum * @return 校正位 */private static function getCheckCode18($iSum) {$sCode = "";switch ($iSum % 11) {case 10 :$sCode = "2";break;case 9 :$sCode = "3";break;case 8 :$sCode = "4";break;case 7 :$sCode = "5";break;case 6 :$sCode = "6";break;case 5 :$sCode = "7";break;case 4 :$sCode = "8";break;case 3 :$sCode = "9";break;case 2 :$sCode = "x";break;case 1 :$sCode = "0";break;case 0 :$sCode = "1";break;}return $sCode;}}