首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 依據身分證字號計算年齡:精確到生日是否已過、正則驗證格式、支援新舊制身分證、單元測試範例

     編輯:PHP 相關知識

核心邏輯

身分證字號第 7-14 碼為出生日期 (YYYYMMDD)。年齡計算規則:**生日當天算滿 1 歲**,未到生日不算。

完整函數 (含格式驗證)

<?php
function getAgeFromId(string $id): ?int {
    // 1. 格式驗證 (台灣身分證: 1 字母 + 9 數字)
    if (!preg_match('/^[A-Z][12]\d{8}$/', $id)) {
        return null; // 或拋出 InvalidArgumentException
    }
    
    // 2. 解析出生日期
    $birthStr = substr($id, 1, 8); // YYYYMMDD
    $birth = DateTime::createFromFormat('Ymd', $birthStr);
    if (!$birth) return null; // 非法日期 (如 20240230)
    
    // 3. 計算年齡
    $today = new DateTime('today'); // 00:00:00
    $age = $today->diff($birth)->y;
    
    // diff 已正確處理「生日是否已過」:若今天 < 今年生日,y 會少 1
    return $age;
}

// 單元測試
$tests = [
    ['A123456789', '1990-01-01', 34], // 假設今天 2024-12-20
    ['A123456789', '2024-12-20', 0],  // 今天生日
    ['A123456789', '2024-12-21', 0],  // 生日未到
];
foreach ($tests as [$id, $birth, $expected]) {
    $age = getAgeFromId($id);
    echo "ID: $id, 年齡: $age, 預期: $expected, " . ($age === $expected ? '✅' : '❌') . "\n";
}

支援新式身分證 (2021/01/01 後核發,第 2 碼為 8/9)

// 新制:第 2 碼 8=男, 9=女 (外國人統一證號另行規定)
if (!preg_match('/^[A-Z][1289]\d{8}$/', $id)) {
    return null;
}

進階:身分證檢查碼驗證 (防偽)


function validateTaiwanId(string $id): bool {
    if (!preg_match('/^[A-Z][1289]\d{8}$/', $id)) return false;
    
    // 字母對應數值表
    $letterMap = [
        'A'=>10,'B'=>11,'C'=>12,'D'=>13,'E'=>14,'F'=>15,'G'=>16,'H'=>17,'I'=>34,
        'J'=>18,'K'=>19,'L'=>20,'M'=>21,'N'=>22,'O'=>35,'P'=>23,'Q'=>24,'R'=>25,
        'S'=>26,'T'=>27,'U'=>28,'V'=>29,'W'=>32,'X'=>30,'Y'=>31,'Z'=>33
    ];
    $c1 = $letterMap[$id[0]] ?? 0;
    $n1 = (int)$id[1];
    $sum = intdiv($c1, 10) + ($c1 % 10) * 9 + $n1 * 8;
    for ($i = 2; $i <= 9; $i++) {
        $sum += (int)$id[$i] * (10 - $i);
    }
    $check = (10 - $sum % 10) % 10;
    return $check === (int)$id[10];
}

應用場景

  • 會員註冊自動填入生日、計算年齡、驗證身分證真偽。
  • 年齡限制商品 (酒菸、18+ 遊戲) 伺服端二次核驗。
  • 保險/金融試算精確計算保齡 (虛歲/實歲區分)。
  • 資料清洗:批量驗證匯入資料中身分證格式與檢查碼。

效能優化

  • 靜態快取 $letterMap 避免重複建立陣列。
  • 大量計算時改用 strtotime + 整數運算 (如原文),但 DateTime::diff 可讀性高、自動處理閏年、時區,現代 CPU 差異可忽略。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved