萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 從身分證字號解析性別與生日:一行程式碼搞定

前言

中國大陸身分證字號編碼規則固定:15 碼(舊版)與 18 碼(新版)皆將生日編碼於固定位置,性別則由倒數第 2 位(15碼)或倒數第 2 位(18碼)奇偶決定。本文提供極簡解析函式,並說明原理。

核心解析函式

<?php
/**
 * 從身分證字號解析生日與性別
 * @param string $idcard 身分證字號
 * @return array ['birth' => 'YYYY-MM-DD', 'gender' => '男|女'] 或 false
 */
function parse_idcard(string $idcard): array|false
{
    $idcard = strtoupper(trim($idcard));
    $len = strlen($idcard);

    // 格式快速檢核
    if (!preg_match('/^(\d{15}|\d{17}[\dX])$/', $idcard)) {
        return false;
    }

    // 解析生日
    if ($len === 15) {
        // 15碼:第7-12位 YYMMDD,年份補19
        $birthRaw = '19' . substr($idcard, 6, 6);
    } else {
        // 18碼:第7-14位 YYYYMMDD
        $birthRaw = substr($idcard, 6, 8);
    }
    $timestamp = strtotime($birthRaw);
    if ($timestamp === false) {
        return false; // 生日不合法
    }
    $birth = date('Y-m-d', $timestamp);

    // 解析性別:倒數第2位(15碼為第14位,18碼為第17位),奇數=男、偶數=女
    $sexDigit = $idcard[$len - 2]; // 統一取倒數第2個字元
    $gender = ((int)$sexDigit % 2 === 1) ? '男' : '女';

    return ['birth' => $birth, 'gender' => $gender];
}

// 測試
var_dump(parse_idcard('110105199003078531')); // 18碼
// ['birth' => '1990-03-07', 'gender' => '男']

var_dump(parse_idcard('110105900307853'));    // 15碼
// ['birth' => '1990-03-07', 'gender' => '男']

原理說明

版本長度生日位置生日格式性別位置性別規則
舊版157-12 (6 碼)YYMMDD第 14 碼 (索引 13)奇=男、偶=女
新版187-14 (8 碼)YYYYMMDD第 17 碼 (索引 16)奇=男、偶=女

統一取 $idcard[strlen($idcard)-2] 即為性別碼,極度簡潔。

進階:整合驗證與解析

function validate_and_parse_idcard(string $idcard): array
{
    $result = parse_idcard($idcard);
    if ($result === false) {
        throw new InvalidArgumentException('身分證字號格式錯誤或生日不合法');
    }
    // 18碼額外驗證校驗碼
    if (strlen($idcard) === 18) {
        $weights = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2];
        $checkMap = ['1','0','X','9','8','7','6','5','4','3','2'];
        $sum = 0;
        for ($i=0; $i<17; $i++) {
            $sum += (int)$idcard[$i] * $weights[$i];
        }
        if ($idcard[17] !== $checkMap[$sum % 11]) {
            throw new InvalidArgumentException('身分證校驗碼錯誤');
        }
    }
    return $result;
}

應用場景

  • 會員註冊自動填入生日、性別,減少使用者輸入
  • 實名認證前端即時驗證(配合 AJAX)
  • 資料匯入清洗:批次解析 Excel/CSV 中的身分證欄位
  • 年齡計算:floor((time() - strtotime($birth)) / 31556926)

注意事項

  • 編碼:確保輸入字串為 UTF-8,避免 substr 位元組偏移導致中文亂碼(身分證純數字+X 無此問題)。
  • 嚴謹度:生產環境建議加入地址碼(前 6 碼)驗證、年齡合理範圍檢核。
  • 隱私:解析後勿記錄完整身分證,僅存生日、性別等脫敏資料。

結語

身分證字號編碼規則固定且公開,利用 PHP 字串操作與 strtotime 即可輕鬆解析生日與性別。將上述函式封裝為工具類,配合單元測試覆蓋邊界情況(閏年、15/18 碼轉換、X 校驗碼),即可安心應用於各類實名制業務中。

copyright © 萬盛學電腦網 all rights reserved