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

PHP date() 函數實作萬年曆:從時間戳到完整日曆表格輸出

     編輯:PHP 相關知識

前言

PHP date() 函數功能強大,支援豐富的格式化字元。本文實作一個 LampDate 類,給定起始/結束日期,自動生成完整的 HTML 表格日曆,支援多月份跨越、今日高亮、範圍標記、CSS/JS 外掛,展示 date() 進階應用。

一、date() 格式化字元完整對照表

字元說明範例
日
d月份中的第幾天(雙位數,前導零)01-31
D星期幾縮寫(3 字母)Mon-Sun
j月份中的第幾天(無前導零)1-31
l星期幾完整名稱Sunday-Saturday
NISO-8601 星期數(1=週一,7=週日)1-7
S日期序數後綴st, nd, rd, th
w星期數(0=週日,6=週六)0-6
z年份中的第幾天0-365
週
WISO-8601 年份週數42
月
F月份完整名稱January-December
m月份雙位數01-12
M月份縮寫Jan-Dec
n月份無前導零1-12
t該月總天數28-31
年
L是否閏年1/0
Y4 位數年份2024
y2 位數年份24
時間
H24 小時制雙位數00-23
i分鐘雙位數00-59
s秒數雙位數00-59
完整格式
cISO 86012024-01-15T10:30:00+08:00
rRFC 822Mon, 15 Jan 2024 10:30:00 +0800
UUnix 時間戳1705285800

二、LampDate 類核心實現

屬性設計

class LampDate {
    private $start_year, $start_month, $start_day;
    private $end_year, $end_month, $end_day;
    private $start_time, $end_time;      // 時間戳
    private $start, $end;                // 起始月首/結束月尾時間戳
    private $day_count;                  // 總天數
    private $week = ['星期一','星期二','星期三','星期四','星期五','星期六','星期日'];
    private $css, $script;               // 外部樣式/腳本路徑
}

建構子:參數預設與時間戳計算

public function __construct(
    $start_year = '2024', $start_month = '1', $start_day = '1',
    $end_year = '2024', $end_month = '12', $end_day = '31',
    $css = 'style.css', $script = 'js.js'
) {
    // 賦值
    $this->start_year = $start_year;  $this->start_month = $start_month;  $this->start_day = $start_day;
    $this->end_year = $end_year;      $this->end_month = $end_month;      $this->end_day = $end_day;
    $this->css = $css;  $this->script = $script;

    // 關鍵時間戳計算
    $this->start_time = strtotime("{$start_year}-{$start_month}-{$start_day}");
    $this->end_time   = strtotime("{$end_year}-{$end_month}-{$end_day}");
    $this->start      = strtotime("{$start_year}-{$start_month}-01");           // 起始月第一天
    $this->end        = strtotime("{$end_year}-{$end_month}-" . date('t', $this->end_time)); // 結束月最後一天
    $this->day_count  = ($this->end - $this->start) / 86400; // 總天數
}

核心輸出方法:get_datetab()

public function get_datetab($i = 0) {
    $str = $this->get_style(); // 載入 CSS/JS
    
    for ($i = 0, $t = 1; $i <= $this->day_count; $i++) {
        $current = $this->start + $i * 86400; // 當天時間戳
        
        // 月初:輸出表頭與星期列
        if (date('d', $current) == '01') {
            $str .= $this->get_caption($i);  // 年月標題
            $str .= $this->get_week();       // 星期一至日
        }
        
        // 月首前空格
        $str .= $this->get_space_front($i);
        // 日期格
        $str .= $this->get_date($i);
        // 月尾後空格
        $str .= $this->get_space_back($i);
        // 換行與補齊行
        $str .= $this->get_rows($i, $t);
        // 月末結束表格
        $str .= $this->get_endtab($i, $t);
    }
    return $str;
}

輔助方法精選

// 表頭:年月
private function get_caption($i) {
    $current = $this->start + $i * 86400;
    return "";
}

// 星期列
private function get_week() {
    $str = "";
    foreach ($this->week as $w => $name) {
        $str .= "";
    }
    return $str . "";
}

// 月首前空格(根據星期幾)
private function get_space_front($i) {
    $current = $this->start + $i * 86400;
    if (date('d', $current) == '01') {
        $str = (date('N', $current) == '1') ? "" : ""; // 週一換行
        $empty = (int)date('N', $current) - 1; // 週一=0格,週日=6格
        $str .= str_repeat("", $empty);
        return $str;
    }
    return (date('N', $current) == '1') ? "" : ""; // 非月初只管換行
}

// 日期格(高亮:起始綠、結束紅、今日深紅)
private function get_date($i) {
    $current = $this->start + $i * 86400;
    $cls = 'date';
    if (date('Ymd', $current) == "{$this->start_year}{$this->start_month}{$this->start_day}") $cls = 'start';
    elseif (date('Ymd', $current) == "{$this->end_year}{$this->end_month}{$this->end_day}") $cls = 'end';
    elseif (date('ymd', $current) == date('ymd')) $cls = 'today';
    return "";
}

// 月尾後空格
private function get_space_back($i) {
    $current = $this->start + $i * 86400;
    if (date('d', $current) == date('t', $current)) {
        $empty = 7 - (int)date('N', $current);
        return str_repeat("", $empty);
    }
    return '';
}

// 換行與補齊 6 行
private function get_rows($i, &$t) {
    $current = $this->start + $i * 86400;
    $str = '';
    if (date('N', $current) == '7') { // 週日換行
        $str .= "";
        if (date('d', $current) == date('t', $current)) $t--; // 月末週日行數修正
        $t++;
    }
    // 月末不足 6 行補空行
    if (date('d', $current) == date('t', $current) && $t < 6) {
        while ($t < 6) {
            $str .= "" . str_repeat("", 7) . "";
            $t++;
        }
    }
    return $str;
}

// 結束表格
private function get_endtab($i, &$t) {
    $current = $this->start + $i * 86400;
    if (date('d', $current) == date('t', $current)) {
        $t = 1; // 重置行計數
        return "
" . date('Y年m月', $current) . "
$name
" . date('j', $current) . "
"; } return ''; } // 載入外部 CSS/JS private function get_style() { $str = ""; return $str; }

三、使用範例

<?php
require_once 'LampDate.class.php';

// 2024 年全年日曆
$cal = new LampDate('2024', '1', '1', '2024', '12', '31', 'calendar.css', 'calendar.js');
echo $cal->get_datetab();

// 指定範圍:2024 年 3 月 15 日至 5 月 20 日
$cal2 = new LampDate('2024', '3', '15', '2024', '5', '20');
echo $cal2->get_datetab();

四、CSS 樣式範例 (calendar.css)

table { border-collapse: collapse; margin: 20px auto; font-family: sans-serif; }
.caption { background: #5CACEE; color: white; font-weight: bold; height: 30px; font-size: 1.2em; }
.week { background: #B0E0E6; height: 30px; }
.week th { width: 40px; text-align: center; }
.date { height: 30px; text-align: center; border: 1px solid #eee; }
.empty { background: #EDEDED; }
.today { background: #EE2C2C; color: white; font-weight: bold; }
.start { background: #7CCD7C; color: white; }
.end { background: #EE6363; color: white; }

五、JS 互動範例 (calendar.js)

document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('.date, .today, .start, .end').forEach(td => {
        td.style.cursor = 'pointer';
        td.addEventListener('click', () => {
            const dateText = td.textContent.trim();
            const caption = td.closest('table').querySelector('.caption').textContent;
            alert(`選中日期: ${caption} ${dateText}日`);
            // 這裡可觸發 AJAX 載入當日行程...
        });
    });
});

六、現代化替代方案

  • DateTime / DateTimeImmutable:物件導向、時區支援更好、鏈式操作
  • IntlCalendar:國際化日曆(農曆、波斯曆等)、ICU 庫支援
  • Carbon (Laravel):流暢介面、人性化差值、測試友善
// Carbon 範例
use Carbon\Carbon;
$period = CarbonPeriod::create('2024-01-01', '2024-12-31');
foreach ($period as $date) {
    echo $date->format('Y-m-d l') . "\n";
}

結語

透過 date()、strtotime()、時間戳運算,我們實現了功能完整的萬年曆類。理解「時間戳為核心、格式化為表現」的設計思想,能靈活應對各種日期計算與顯示需求。現代專案建議採用 DateTime 或 Carbon 等更高階抽象,減少手動時間戳運算的錯誤風險。

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