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

PHP 實現從指定日期向前推算 N 個月的函數

     編輯:PHP 相關知識

前言

作者 bjbs_270 分享一個月報表統計常用的功能:給定起始日期,向前推算 N 個月份 (格式 Y-m)。文中包含完整程式碼與執行結果。

函數實現

<?php
/**
 * 從指定時間向下推 N 個月
 * @param string $ymd 起始日期 (格式 Y-m-d),預設為今天
 * @param int $len 推算月數,預設 12
 * @return array 月份陣列 (格式 Y-m)
 */
function month($ymd = '', $len = 12) {
    $month = array();
    $lang = '<meta http-equiv="Content-Type" content="text/html; charset=gb2312">';

    // 參數驗證
    if ($ymd) {
        if (!ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $ymd)) {
            echo "日期格式錯誤"; exit;
        }
    }
    if ($len) {
        if (!ereg("[0-9]+", $len)) {
            echo $lang . "長度參數錯誤"; exit;
        }
    }

    for ($i = 0; $i < $len; $i++) {
        if ($i == 0) {
            $mktime = $ymd ? strtotime($ymd) : time();
        }
        $month[] = date("Y-m", $mktime); // 可依需求調整格式
        $day = date("t", $mktime); // 當月總天數
        if ($i == 0)
            $reday = date("d", $mktime); // 第一個月用實際日期
        else
            $reday = $day; // 後續月用該月最後一天

        $t1 = $mktime;
        // 關鍵邏輯:減去天數到上個月同一天 (或最後一天)
        $mktime = date("Y-m-d", mktime(
            date("H", $t1), date("i", $t1), date("s", $t1),
            date("m", $t1), date("d", $t1) - $reday, date("Y", $t1)
        ));
        $mktime = strtotime($mktime);
    }
    return $month;
}

// 測試
$month = month();
foreach ($month as $key => $v) {
    echo $v . "<br>";
}
?>

執行結果 (假設今天 2005-01-01)

2005-01
2004-12
2004-11
2004-10
2004-09
2004-08
2004-07
2004-06
2004-05
2004-04
2004-03
2004-02

程式碼分析與改進建議

核心邏輯

利用 mktime() 的「日期溢位」特性:將日部分減去當月天數 ($reday),自動推算到上個月。第一次迴圈用實際日期,後續用各月最後一天 (date("t")) 確保落在月末。

潛在問題

  • 使用已棄用 ereg() 函數 (PHP 5.3+ 移除),建議改用 preg_match()。
  • 若起始日為 31 號且上個月無 31 號,mktime() 會自動調整 (如 3/31 - 31 天 → 2/28 或 2/29),邏輯正確。
  • 變數命名 $mktime 與函數名衝突,易造成混淆。

現代化重寫 (PHP 7+)

function getPreviousMonths(\DateTimeInterface $start = null, int $count = 12): array {
    $start = $start ?? new DateTime();
    $months = [];
    $current = clone $start;
    for ($i = 0; $i < $count; $i++) {
        $months[] = $current->format('Y-m');
        $current->modify('first day of last month'); // 直接跳到上個月 1 號
    }
    return $months;
}

總結

原函數展示了早期 PHP 日期運算的巧思,現代開發強烈建議使用 DateTime 類別,語意清晰且避免時區與閏年陷阱。

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