驗證日期格式與實際有效性(如 2013-02-29 不存在)看似簡單,實則易漏判。本文提供一個健壯的驗證函數,利用 strtotime() 解析與 date() 格式化回檢,支援多種日期格式。
<?php
/**
* 驗證日期字串是否為有效日期
* @param string $date 待驗證日期字串
* @param array $formats 允許的格式陣列(預設 Y-m-d, Y/m/d)
* @return bool
*/
function checkDateIsValid($date, $formats = ['Y-m-d', 'Y/m/d']) {
$unixTime = strtotime($date);
if (!$unixTime) {
return false; // 格式完全無法解析
}
// 回檢:格式化後是否等於原字串
foreach ($formats as $format) {
if (date($format, $unixTime) === $date) {
return true;
}
}
return false;
}
?>
strtotime() 嘗試解析字串為時間戳。失敗回傳 false,表示格式錯誤(如 2013-09-ha)。date() 格式化時間戳,若有任一格式化結果 完全等於 原字串,則日期有效。2012-02-29 通過,2013-02-29 失敗)。<?php
var_dump(checkDateIsValid('2013-09-10')); // true
var_dump(checkDateIsValid('2013-09-ha')); // false
var_dump(checkDateIsValid('2012-02-29')); // true (閏年)
var_dump(checkDateIsValid('2013-02-29')); // false (平年)
var_dump(checkDateIsValid('2024/12/31', ['Y/m/d'])); // true
var_dump(checkDateIsValid('31-12-2024', ['d-m-Y'])); // true (需加入格式)
?>
| 優點 | 缺點/限制 |
|---|---|
| 程式碼簡潔,無需複雜正則 | strtotime() 解析範圍受限(32位系統 1970-2038) |
| 自動處理閏年、月份天數 | 極特殊格式(如 2024年12月31日)無法解析 |
| 支援多格式彈性驗證 | 若格式不在 $formats 中會誤判為無效 |
<?php
function checkDateModern($date, $format = 'Y-m-d') {
$dt = DateTime::createFromFormat($format, $date);
return $dt && $dt->format($format) === $date;
}
// 用法
var_dump(checkDateModern('2013-02-29', 'Y-m-d')); // false
?>
DateTime::createFromFormat 精確控制格式、不受 2038 問題影響,建議新專案採用。