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

PHP 日期時間處理:獲取本月/上月/下月首尾日期、天數、 strtotime 智能解析完全指南

     編輯:PHP 綜合知識

核心函數:strtotime 相對格式

strtotime 支援極其豐富的自然語言相對時間:

<?php
echo date('Y-m-d', strtotime('first day of this month'));   // 本月 1 號
echo date('Y-m-d', strtotime('last day of this month'));    // 本月最後一天
echo date('Y-m-d', strtotime('first day of last month'));   // 上月 1 號
echo date('Y-m-d', strtotime('last day of last month'));    // 上月最後一天
echo date('Y-m-d', strtotime('first day of next month'));   // 下月 1 號
echo date('Y-m-d', strtotime('last day of next month'));    // 下月最後一天
echo date('t', strtotime('this month'));                    // 本月天數
echo date('t', strtotime('last month'));                    // 上月天數
?>

封裝函數:獲取月份首尾日期 (Y-m-d)

<?php
/**
 * 獲取指定月份首尾日期
 * @param string $baseDate 基準日期 (任意格式 strtotime 可解析)
 * @param int    $monthOffset 月份偏移:0=本月, -1=上月, 1=下月
 * @return array ['first'=>'Y-m-d', 'last'=>'Y-m-d', 'days'=>int]
 */
function getMonthRange(string $baseDate = 'now', int $monthOffset = 0): array {
    $first = date('Y-m-01', strtotime("$baseDate $monthOffset month"));
    $last  = date('Y-m-t', strtotime($first)); // 't' = 該月天數
    return [
        'first' => $first,
        'last'  => $last,
        'days'  => (int)date('t', strtotime($first)),
    ];
}

// 使用
print_r(getMonthRange('2024-01-15', 0));  // 本月
print_r(getMonthRange('2024-01-15', -1)); // 上月
print_r(getMonthRange('2024-01-15', 1));  // 下月
/* 輸出:
Array([first]=>2024-01-01 [last]=>2024-01-31 [days]=>31)
Array([first]=>2023-12-01 [last]=>2023-12-31 [days]=>31)
Array([first]=>2024-02-01 [last]=>2024-02-29 [days]=>29)  // 閏年自動處理
*/

進階:DateTime 物件導向風格 (PHP 5.2+)

<?php
function getMonthRangeOO(string $baseDate = 'now', int $monthOffset = 0): array {
    $dt = new DateTime($baseDate);
    $dt->modify("first day of $monthOffset month"); // 負數自動處理
    $first = $dt->format('Y-m-d');

    $dt->modify('last day of this month');
    $last = $dt->format('Y-m-d');
    $days = (int)$dt->format('t');

    return compact('first', 'last', 'days');
}

常見陷阱與修正

錯誤寫法問題正確寫法
date('Y-m-d', strtotime('-1 month'))1月31日 -1月 → 12月31日 (正確),但 3月31日 -1月 → 2月28/29日 (非預期)strtotime('first day of last month')
date('Y-m-d', strtotime('+1 month'))1月31日 +1月 → 3月3日 (因 2月無31日)strtotime('first day of next month')
手動拼接 date('Y-m-01', strtotime("$year-$month-01"))月份 0 或 13 導致 1970 年使用 modify('first day of ...') 自動跨年

實戰:生成月份選項 (下拉框)

<?php
function getMonthOptions(int $startYear = 2020, int $endYear = 2030): array {
    $options = [];
    for ($y = $startYear; $y <= $endYear; $y++) {
        for ($m = 1; $m <= 12; $m++) {
            $value = sprintf('%04d-%02d', $y, $m);
            $label = date('Y年m月', strtotime($value));
            $options[$value] = $label;
        }
    }
    return $options;
}

// HTML
echo '';

日期區間查詢 SQL 構建

<?php
function buildMonthWhere(string $column, string $baseDate = 'now', int $offset = 0): string {
    $range = getMonthRange($baseDate, $offset);
    // 包含首尾全天:>= 首日 00:00:00  AND < 下月首日 00:00:00
    $nextMonthFirst = date('Y-m-d', strtotime($range['first'] . ' +1 month'));
    return "`$column` >= '{$range['first']} 00:00:00' AND `$column` < '$nextMonthFirst 00:00:00'";
}

// 使用
$where = buildMonthWhere('created_at', '2024-01-15', -1);
// `created_at` >= '2023-12-01 00:00:00' AND `created_at` < '2024-01-01 00:00:00'

現代最佳實踐:Carbon (Laravel/獨立使用)

composer require nesbot/carbon
<?php
use Carbon\Carbon;

$now = Carbon::now();
echo $now->startOfMonth()->format('Y-m-d'); // 本月首日
echo $now->endOfMonth()->format('Y-m-d');   // 本月末日
echo $now->copy()->subMonth()->startOfMonth(); // 上月首日
echo $now->daysInMonth;                     // 本月天數

// 區間迭代
$period = CarbonPeriod::create('2024-01-01', '2024-12-31', '1 month');
foreach ($period as $date) {
    echo $date->format('Y-m') . "\n";
}

Carbon 提供不可變物件、鏈式調用、國際化、測試輔助 (Carbon::setTestNow()),是現代 PHP 日期處理首選。

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