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

PHP 依身分證字號計算年齡(支援新舊制、生日未到邏輯、效能優化)

     編輯:PHP 相關知識

身分證字號結構(中華民國)

  • 第 1 碼:英文字母(地區代碼)。
  • 第 2 碼:性別(1 男、2 女、8/9 新制外籍/大陸港澳)。
  • 第 3-8 碼:出生日期(YYMMDD),民國年。
  • 第 9-10 碼:流水號。
  • 第 11 碼:檢查碼。

核心函式


/**
 * 依身分證字號計算滿年齡
 * @param string $id 身分證字號(含舊制 10 碼、新制 11 碼)
 * @return int|false 年齡,格式錯誤回傳 false
 */
function getAgeFromId(string $id): int|false {
    // 1. 格式驗證(簡化:長度 10 或 11、前 2 碼格式)
    $id = trim($id);
    if (!preg_match('/^[A-Z][1289]\d{8,9}$/i', $id)) return false;

    // 2. 解析出生日期(第 3-8 碼,共 6 碼:YYMMDD)
    $birthStr = substr($id, 2, 6); // 例:900101
    if (strlen($birthStr) !== 6) return false;

    $rocYear  = (int) substr($birthStr, 0, 2); // 民國年
    $month    = (int) substr($birthStr, 2, 2);
    $day      = (int) substr($birthStr, 4, 2);

    // 3. 驗證月份日期合法性
    if ($month < 1 || $month > 12 || $day < 1 || $day > 31) return false;
    if (!checkdate($month, $day, $rocYear + 1911)) return false; // 民國轉西元

    // 4. 建立生日 DateTime(時區設為 Asia/Taipei)
    $birthDate = new DateTime(
        sprintf('%04d-%02d-%02d', $rocYear + 1911, $month, $day),
        new DateTimeZone('Asia/Taipei')
    );

    // 5. 今日日期(同時區)
    $today = new DateTime('today', new DateTimeZone('Asia/Taipei'));

    // 6. 計算滿年齡:生日已過則 +1,未過則不加
    $age = $today->diff($birthDate)->y;
    // diff 已正確處理「生日未到」情況,直接回傳 y 即為滿年齡

    return $age;
}

// 使用範例
echo getAgeFromId('A123456789'); // 依出生日期計算
echo getAgeFromId('A1900101123'); // 新制 11 碼

關鍵細節說明

細節處理方式
民國年轉西元+ 1911(民國 1 年 = 1912 年)
生日未到邏輯DateTime::diff() 內建正確計算滿年齡,無需手動比較月日
時區強制 Asia/Taipei,避免跨日界問題
舊制 10 碼 / 新制 11 碼同樣取第 3-8 碼為出生日期,長度差異在流水號與檢查碼
外籍/大陸港澳 (性別碼 8/9)同樣適用,出生日期格式相同
檢查碼驗證本函式未實作,如需完整驗證請加入加權加總模 10 算法

效能優化:批次計算


function getAgesBatch(array $ids): array {
    $today = new DateTime('today', new DateTimeZone('Asia/Taipei'));
    $results = [];
    foreach ($ids as $id) {
        $results[$id] = getAgeFromId($id); // 可內聯優化,避免重複建立 $today
    }
    return $results;
}

結語

善用 DateTime::diff() 內建滿年齡計算、強制時區、驗證月份日期合法性,即可穩健實現「身分證字號計算年齡」。批次處理時複用 DateTime('today') 物件,避免重複建立開銷。如需完整身分證驗證(檢查碼、地區碼對照),建議引入成熟套件(如 laravel-id-validation、taiwan-id-validator)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved