| 特性 | strtotime() | mktime() |
|---|---|---|
| 輸入方式 | 英文自然語言文字 | 分離的數值參數 |
| 可讀性 | 極高 | 較低 |
| 靈活度 | 支援相對時間、複雜描述 | 精確控制每個時間元件 |
| 效能 | 需解析字串,稍慢 | 直接運算,較快 |
| 適用場景 | 動態時間描述、相對日期 | 固定格式、高效能需求、避免歧義 |
<?php
// 基準時間:當下
echo date("Y-m-d", strtotime("now")); // 今天
echo date("Y-m-d", strtotime("today")); // 今天 00:00:00
// 相對日期
echo date("Y-m-d", strtotime("-1 day")); // 昨天
echo date("Y-m-d", strtotime("+1 week")); // 下週同天
echo date("Y-m-d", strtotime("first day of this month")); // 本月 1 號
echo date("Y-m-d", strtotime("last day of last month")); // 上月最後一天
// 週邊界(重點!)
echo date("Y-m-d", strtotime("monday this week")); // 本週一
echo date("Y-m-d", strtotime("sunday this week")); // 本週日
echo date("Y-m-d", strtotime("monday last week")); // 上週一
echo date("Y-m-d", strtotime("sunday last week")); // 上週日
// 季度邊界
echo date("Y-m-d", strtotime("first day of this quarter"));
echo date("Y-m-d", strtotime("last day of last quarter"));
?>
語法:mktime(時, 分, 秒, 月, 日, 年),參數從右至左可省略(預設為當前時間)。
<?php
// 取得本週一 00:00:00
$weekStart = mktime(0, 0, 0, date("m"), date("d") - date("w") + 1, date("Y"));
// 取得本週日 23:59:59
$weekEnd = mktime(23, 59, 59, date("m"), date("d") - date("w") + 7, date("Y"));
echo "本週起:" . date("Y-m-d H:i:s", $weekStart) . "<br>";
echo "本週迄:" . date("Y-m-d H:i:s", $weekEnd) . "<br>";
?>
原理:date("w") 回傳 0(日)~6(六),date("d") - date("w") + 1 即為本週一日期。
<?php
$lastWeekStart = mktime(0, 0, 0, date("m"), date("d") - date("w") + 1 - 7, date("Y"));
$lastWeekEnd = mktime(23, 59, 59, date("m"), date("d") - date("w") + 7 - 7, date("Y"));
?>
<?php
$monthStart = mktime(0, 0, 0, date("m"), 1, date("Y"));
$monthEnd = mktime(23, 59, 59, date("m"), date("t"), date("Y")); // date("t") 為本月總天數
?>
<?php
$lastMonthStart = mktime(0, 0, 0, date("m") - 1, 1, date("Y"));
$lastMonthEnd = mktime(23, 59, 59, date("m"), 0, date("Y")); // 第 0 天 = 上月最後一天
?>
<?php
// 計算本季度首月 (1,4,7,10)
$currentMonth = (int)date("n");
$quarterStartMonth = $currentMonth - ($currentMonth - 1) % 3;
// 季度第一天
$quarterStart = mktime(0, 0, 0, $quarterStartMonth, 1, date("Y"));
// 季度最後一天:取下季第一天減 1 秒,或計算季度末月天數
$quarterEndMonth = $quarterStartMonth + 2;
$quarterEndDay = date("t", mktime(0, 0, 0, $quarterEndMonth, 1, date("Y")));
$quarterEnd = mktime(23, 59, 59, $quarterEndMonth, $quarterEndDay, date("Y"));
echo "本季度起:" . date("Y-m-d", $quarterStart) . "<br>";
echo "本季度迄:" . date("Y-m-d", $quarterEnd) . "<br>";
?>
強烈建議使用 OOP 風格的 DateTime/DateTimeImmutable,功能更強、時區處理正確、可鏈式呼叫。
<?php
$now = new DateTime();
// 本週一
$weekStart = clone $now;
$weekStart->modify('monday this week')->setTime(0, 0, 0);
// 本週日
$weekEnd = clone $now;
$weekEnd->modify('sunday this week')->setTime(23, 59, 59);
// 本月第一天
$monthStart = clone $now;
$monthStart->modify('first day of this month')->setTime(0, 0, 0);
// 本月最後一天
$monthEnd = clone $now;
$monthEnd->modify('last day of this month')->setTime(23, 59, 59);
// 本季度
$quarterStart = clone $now;
$quarterStart->modify('first day of this quarter')->setTime(0, 0, 0);
$quarterEnd = clone $now;
$quarterEnd->modify('last day of this quarter')->setTime(23, 59, 59);
echo "本週:{$weekStart->format('Y-m-d')} ~ {$weekEnd->format('Y-m-d')}<br>";
echo "本月:{$monthStart->format('Y-m-d')} ~ {$monthEnd->format('Y-m-d')}<br>";
echo "本季:{$quarterStart->format('Y-m-d')} ~ {$quarterEnd->format('Y-m-d')}<br>";
?>
<?php
$now = new DateTimeImmutable();
$weekStart = $now->modify('monday this week')->setTime(0, 0, 0); // 回傳新物件
$weekEnd = $now->modify('sunday this week')->setTime(23, 59, 59);
// $now 本身不變
?>
<?php
/**
* 取得常用時間範圍的起迄時間戳
* @return array ['range_name' => ['start' => timestamp, 'end' => timestamp]]
*/
function getCommonDateRanges(): array {
$now = new DateTimeImmutable();
$ranges = [];
// 今天
$ranges['today'] = [
'start' => $now->setTime(0, 0, 0)->getTimestamp(),
'end' => $now->setTime(23, 59, 59)->getTimestamp(),
];
// 昨天
$yesterday = $now->modify('-1 day');
$ranges['yesterday'] = [
'start' => $yesterday->setTime(0, 0, 0)->getTimestamp(),
'end' => $yesterday->setTime(23, 59, 59)->getTimestamp(),
];
// 本週 (週一~週日)
$ranges['this_week'] = [
'start' => $now->modify('monday this week')->setTime(0, 0, 0)->getTimestamp(),
'end' => $now->modify('sunday this week')->setTime(23, 59, 59)->getTimestamp(),
];
// 上週
$ranges['last_week'] = [
'start' => $now->modify('monday last week')->setTime(0, 0, 0)->getTimestamp(),
'end' => $now->modify('sunday last week')->setTime(23, 59, 59)->getTimestamp(),
];
// 本月
$ranges['this_month'] = [
'start' => $now->modify('first day of this month')->setTime(0, 0, 0)->getTimestamp(),
'end' => $now->modify('last day of this month')->setTime(23, 59, 59)->getTimestamp(),
];
// 上月
$ranges['last_month'] = [
'start' => $now->modify('first day of last month')->setTime(0, 0, 0)->getTimestamp(),
'end' => $now->modify('last day of last month')->setTime(23, 59, 59)->getTimestamp(),
];
// 本季度
$ranges['this_quarter'] = [
'start' => $now->modify('first day of this quarter')->setTime(0, 0, 0)->getTimestamp(),
'end' => $now->modify('last day of this quarter')->setTime(23, 59, 59)->getTimestamp(),
];
// 本年
$ranges['this_year'] = [
'start' => $now->modify('first day of January')->setTime(0, 0, 0)->getTimestamp(),
'end' => $now->modify('last day of December')->setTime(23, 59, 59)->getTimestamp(),
];
return $ranges;
}
// 使用範例
$ranges = getCommonDateRanges();
foreach ($ranges as $name => $range) {
echo "$name: " . date('Y-m-d H:i:s', $range['start']) . " ~ " . date('Y-m-d H:i:s', $range['end']) . "<br>";
}
?>
<?php
// ❌ 錯誤:依賴伺服器預設時區
date_default_timezone_set('Asia/Taipei'); // 必須明確設定
// ✅ DateTime 明確指定時區
$taipei = new DateTime('now', new DateTimeZone('Asia/Taipei'));
$utc = new DateTime('now', new DateTimeZone('UTC'));
// php.ini 設定預設時區(推薦)
// date.timezone = "Asia/Taipei"
?>
WHERE created_at >= :start AND created_at <= :end