本文目录导读:

在PHP项目中排除节假日计算工作日,通常需要结合法定节假日和调休上班日来实现,以下是几种常见方案的实现思路和代码示例:
基础方案:手动配置节假日数组
<?php
class WorkDayCalculator {
private $holidays = []; // 法定节假日
private $workdays = []; // 调休上班日
public function __construct() {
// 配置2024年节假日(示例)
$this->holidays = [
'2024-01-01', // 元旦
'2024-02-10', // 春节
'2024-02-11',
'2024-02-12',
// ... 其他节假日
];
// 配置2024年调休上班日
$this->workdays = [
'2024-02-04', // 春节调休
'2024-02-18',
// ... 其他调休
];
}
/**
* 判断某天是否为工作日
*/
public function isWorkDay($date) {
$dateStr = date('Y-m-d', strtotime($date));
$weekDay = date('N', strtotime($date)); // 1-7, 1=周一
// 检查是否为节假日
if (in_array($dateStr, $this->holidays)) {
return false;
}
// 检查是否为调休上班日
if (in_array($dateStr, $this->workdays)) {
return true;
}
// 检查是否为周末(周六日)
return !in_array($weekDay, [6, 7]); // 6=周六, 7=周日
}
/**
* 计算N个工作日后的日期
*/
public function addWorkDays($startDate, $days) {
$currentDate = strtotime($startDate);
$addedDays = 0;
while ($addedDays < $days) {
$currentDate = strtotime('+1 day', $currentDate);
if ($this->isWorkDay($currentDate)) {
$addedDays++;
}
}
return date('Y-m-d', $currentDate);
}
/**
* 计算两个日期之间的工作日天数
*/
public function countWorkDays($startDate, $endDate) {
$workDays = 0;
$current = strtotime($startDate);
$end = strtotime($endDate);
while ($current <= $end) {
if ($this->isWorkDay($current)) {
$workDays++;
}
$current = strtotime('+1 day', $current);
}
return $workDays;
}
}
// 使用示例
$calculator = new WorkDayCalculator();
echo $calculator->isWorkDay('2024-02-10'); // false (春节)
echo $calculator->isWorkDay('2024-02-04'); // true (调休上班)
echo $calculator->addWorkDays('2024-01-01', 10); // 计算10个工作日后的日期
?>
使用API获取实时节假日数据
<?php
class HolidayAPICalculator {
/**
* 从API获取年度节假日数据
*/
public function fetchHolidays($year) {
$url = "https://api.apihubs.cn/holiday/get?year={$year}&month=0&size=366";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
$holidays = [];
$workdays = [];
if (isset($data['data']['list'])) {
foreach ($data['data']['list'] as $item) {
if ($item['holiday'] === 1) {
$holidays[] = $item['date'];
} else if ($item['holiday'] === 2) {
$workdays[] = $item['date'];
}
}
}
return ['holidays' => $holidays, 'workdays' => $workdays];
}
// 其他方法同第一种方案...
}
?>
使用第三方扩展包
Carbon + CarbonHolidays
<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
// 安装: composer require cmixin/holidays
class AdvancedWorkDayCalculator {
/**
* 使用Carbon扩展包计算工作日
*/
public function addWorkDaysWithCarbon($startDate, $days, $country = 'CN') {
$carbon = Carbon::parse($startDate);
$added = 0;
while ($added < $days) {
$carbon->addDay();
// 检查是否为工作日(结合节假日)
if (!$carbon->isHoliday() && !$carbon->isWeekend()) {
$added++;
}
// 如果是调休上班日
if ($carbon->isWorkday()) {
$added++;
}
}
return $carbon->format('Y-m-d');
}
}
?>
完整的生产环境方案
<?php
class ProductionWorkDayCalculator {
private $holidayData = [];
private $rawData = [];
public function __construct() {
// 从文件或数据库加载预计算的节假日数据
$this->loadHolidayData();
}
/**
* 从文件加载节假日数据
*/
private function loadHolidayData() {
$filePath = __DIR__ . '/holidays.json';
if (file_exists($filePath)) {
$this->rawData = json_decode(file_get_contents($filePath), true);
}
// 将数据转换为易用格式
foreach ($this->rawData as $date => $info) {
if ($info['type'] === 'holiday') {
$this->holidayData['holidays'][] = $date;
} else if ($info['type'] === 'workday') {
$this->holidayData['workdays'][] = $date;
}
}
}
/**
* 智能工作日计算(支持排除特定日期)
*/
public function calculateWorkDays($startDate, $days, $excludeDates = []) {
$current = strtotime($startDate);
$count = 0;
$result = [];
while ($count < $days) {
$current = strtotime('+1 day', $current);
$dateStr = date('Y-m-d', $current);
// 跳过排除日期
if (in_array($dateStr, $excludeDates)) {
continue;
}
// 判断是否为工作日
if ($this->isWorkDay($dateStr)) {
$count++;
$result[] = $dateStr;
}
}
return $result;
}
/**
* 批量判断日期是否为工作日
*/
public function batchCheckWorkDays(array $dates) {
$results = [];
foreach ($dates as $date) {
$results[$date] = $this->isWorkDay($date);
}
return $results;
}
/**
* 获取当前年份的所有节假日
*/
public function getYearHolidays($year = null) {
$year = $year ?: date('Y');
$allHolidays = [];
// 从内置数据或API获取
$holidays = [
// 固定节假日
['name' => '元旦', 'date' => "{$year}-01-01", 'days' => 1],
['name' => '春节', 'date' => $this->getLunarNewYear($year), 'days' => 7],
['name' => '清明节', 'date' => $this->getQingMing($year), 'days' => 3],
['name' => '劳动节', 'date' => "{$year}-05-01", 'days' => 5],
['name' => '端午节', 'date' => $this->getDragonBoat($year), 'days' => 3],
['name' => '中秋节', 'date' => $this->getMidAutumn($year), 'days' => 3],
['name' => '国庆节', 'date' => "{$year}-10-01", 'days' => 7],
];
foreach ($holidays as $holiday) {
$start = strtotime($holiday['date']);
for ($i = 0; $i < $holiday['days']; $i++) {
$allHolidays[] = date('Y-m-d', strtotime("+{$i} day", $start));
}
}
return array_unique($allHolidays);
}
private function isWorkDay($dateStr) {
$weekDay = date('N', strtotime($dateStr));
$isWeekend = in_array($weekDay, [6, 7]); // 6=周六, 7=周日
// 节假日数据库检查
if (in_array($dateStr, $this->holidayData['holidays'] ?? [])) {
return false;
}
// 调休上班日检查
if (in_array($dateStr, $this->holidayData['workdays'] ?? [])) {
return true;
}
// 默认规则:周一至周五为工作日
return !$isWeekend;
}
// 农历日期计算方法(简化版)
private function getLunarNewYear($year) {
// 这里应该使用农历计算库
return "{$year}-02-10"; // 示例值
}
private function getQingMing($year) {
// 清明节通常是4月4日或5日
return "{$year}-04-04"; // 示例值
}
private function getDragonBoat($year) {
// 端午节通常是农历五月初五
return "{$year}-06-10"; // 示例值
}
private function getMidAutumn($year) {
// 中秋节通常是农历八月十五
return "{$year}-09-17"; // 示例值
}
}
// 使用示例
$calculator = new ProductionWorkDayCalculator();
// 计算从今天起10个工作日后的日期
$workDays = $calculator->calculateWorkDays(date('Y-m-d'), 10);
print_r($workDays);
// 批量检查日期
$dates = ['2024-02-10', '2024-02-11', '2024-02-12', '2024-02-13'];
$results = $calculator->batchCheckWorkDays($dates);
print_r($results);
?>
推荐方案与注意事项
推荐方案:
- 小型项目:手动配置节假日数组(方案1)
- 中大型项目:使用第三方API获取实时数据(方案2)
- 生产环境:结合本地缓存+API更新(方案4)
注意事项:
- 区域差异:不同国家/地区的节假日不同
- 更新时间:节假日数据需要每年更新
- 性能优化:对大量日期计算时,建议使用缓存
- 农历计算:中国节假日涉及农历,建议使用专业库
可以使用的PHP农历计算库:
# 安装农历计算库 composer require cmixin/holidays composer require overtrue/chinese-calendar
可以选择根据项目需求选择合适的方案,对于大多数国内项目,建议使用方案4的完整实现。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播