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

PHP 獲取未來 N 個工作日日期(自動跳過周末)的兩種高效實現方法

     編輯:PHP 相關知識

前言

業務系統中常需計算「N 個工作日後的日期」(如訂單預計送達、工單 SLA 截止、薪資發放日),需自動跳過週六、週日。本文提供兩種實現:基礎循環法與封裝函數法,並討論擴展至節假日日曆的方案。

方法一:基礎循環計算(直觀易懂)

<?php
$now = time(); // 或指定起始日期:strtotime('2024-01-08')
$day = 3600 * 24; // 一天秒數
$total = 12;      // 預估循環上限(含周末緩衝)
$days = array();

for ($i = 2; $i < $total; $i++) { // 從後天開始(i=2)
    $timer = $now + $day * $i;
    // date('N') ISO-8601 週幾:1=週一 ... 7=週日
    $num = date('N', $timer) - 2; // 轉換:-1=週一, 0=週二, ..., 3=週五, 4=週六, 5=週日
    
    if ($num >= -1 && $num <= 3) { // 週一至週五
        if (count($days) >= 10) break; // 獲取足夠數量後跳出
        $days[] = date('Y-m-d', $timer);
        $total += 1; // 擴展上限,補償被跳過的周末
    } else {
        $total = ($total == 12) ? $total + 1 : $total; // 首次遇到周末擴展上限
    }
}

// 輸出
$i = 1;
foreach ($days as $day) {
    echo "$i===> $day\n";
    $i++;
}
?>

關鍵邏輯解析

  • date('N') 返回 1-7 (週一-週日),減 2 後:-1=週一, 0=週二, 1=週三, 2=週四, 3=週五, 4=週六, 5=週日。
  • 判斷條件 $num >= -1 && $num <= 3 精確篩選工作日。
  • $total 動態擴展機制:每跳過一個周末,循環上限 +1,確保最終能湊齊所需工作日數量。

方法二:封裝復用函數(推薦生產使用)

<?php
/**
 * 獲取未來 N 個工作日日期數組
 * @param string $date 起始日期,格式 'Y-m-d',默認今天
 * @param int    $count 需要獲取的工作日數量,默認 10
 * @return array 日期字符串數組 ['Y-m-d', ...]
 */
function get_working_days($date = '', $count = 10) {
    $now = empty($date) ? time() : strtotime($date);
    $days = array();
    $i = 1; // 從明天開始 (i=1),或根據業務調整為 0(今天) / 2(後天)
    
    while (count($days) < $count) {
        $timer = $now + 3600 * 24 * $i;
        $weekday = date('N', $timer); // 1-7
        
        if ($weekday >= 1 && $weekday <= 5) { // 週一至週五
            $days[] = date('Y-m-d', $timer);
        }
        $i++;
    }
    return $days;
}

// 使用示例
print_r(get_working_days());           // 未來 10 個工作日
print_r(get_working_days('2024-12-20', 5)); // 從指定日期起未來 5 個工作日

優勢

  • 代碼簡潔、邏輯清晰、無動態上限技巧依賴。
  • 參數化起始日期與數量,復用性強。
  • while 循環自然結束,無需 break。

進階需求:法定節假日支持

僅跳過周末不足以應對中國法定節假日(春節、國慶等)及調休工作日。企業級方案需引入節假日日曆數據源:

方案 A:本地配置文件/數據庫表

// 配置文件 holidays.php
return [
    '2024-01-01' => '元旦',
    '2024-02-10' => '春節',
    '2024-02-11' => '春節',
    // ...
    // 調休上班日
    '2024-02-04' => 'work', // 原周日調休上班
    '2024-02-18' => 'work',
];

// 判斷邏輯
$holidays = include 'holidays.php';
$isWorkday = ($weekday >= 1 && $weekday <= 5) && (!isset($holidays[$date]) || $holidays[$date] === 'work');

方案 B:調用第三方 API(如易源、聚合數據)

function is_workday($date) {
    static $cache = [];
    if (isset($cache[$date])) return $cache[$date];
    
    // 調用 API: https://api.example.com/holiday?date=$date&key=YOUR_KEY
    // 返回: {'is_workday': true/false, 'holiday_name': ''}
    // 這裡用模擬
    $result = @file_get_contents("https://api.example.com/holiday?date=$date");
    $data = json_decode($result, true);
    $cache[$date] = $data['is_workday'] ?? (date('N', strtotime($date)) <= 5);
    return $cache[$date];
}

方案 C:預計算年度工作日陣列(高性能)


// 系統啟動/定時任務預計算全年工作日
$workdays_2024 = [];
for ($d = strtotime('2024-01-01'); $d <= strtotime('2024-12-31'); $d += 86400) {
    $date = date('Y-m-d', $d);
    if (is_workday($date)) $workdays_2024[] = $date;
}
// 運行時直接數組切片,O(1) 獲取
function get_future_workdays($start_date, $count, $workdays_array) {
    $idx = array_search($start_date, $workdays_array);
    if ($idx === false) $idx = 0; // 兜底
    return array_slice($workdays_array, $idx + 1, $count);
}

性能與邊界情況測試

場景方法一方法二預計算法
單次調用 10 天~0.05ms~0.03ms~0.001ms
高併發 (1000 QPS)可接受推薦極佳
跨年計算支持支持需預計算次年
節假日準確性無需接入數據源需預計算數據源

總結

  • 簡單場景: 直接使用 方法二封裝函數,代碼少、Bug 少、易維護。
  • 生產系統: 必須接入節假日日曆(配置文件/數據庫/API),並建議採用年度預計算 + 緩存架構,兼顧準確性與高性能。
  • 時區注意: 服務器時區應設置為目標業務時區(如 date_default_timezone_set('Asia/Shanghai')),避免跨天誤差。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved