本文目录导读:

PHP 工作日计算有多种实现方式,我来介绍几种常见且实用的方法:
简单循环计算(最常用)
<?php
/**
* 计算两个日期之间的工作日天数
* @param string $startDate 开始日期 Y-m-d
* @param string $endDate 结束日期 Y-m-d
* @return int 工作日天数
*/
function getWorkingDays($startDate, $endDate) {
$start = new DateTime($startDate);
$end = new DateTime($endDate);
$end->modify('+1 day'); // 包含结束日期
$workingDays = 0;
$period = new DatePeriod($start, new DateInterval('P1D'), $end);
foreach ($period as $date) {
$dayOfWeek = $date->format('N'); // 1(周一)到7(周日)
if ($dayOfWeek < 6) { // 周一至周五
$workingDays++;
}
}
return $workingDays;
}
// 使用示例
echo getWorkingDays('2024-01-01', '2024-01-31'); // 输出:23
?>
排除节假日
<?php
/**
* 计算工作日(排除节假日)
*/
class WorkingDaysCalculator {
private $holidays = [];
private $workdays = [];
/**
* 添加节假日
*/
public function addHoliday($date) {
$this->holidays[] = $date;
return $this;
}
/**
* 批量添加节假日
*/
public function addHolidays(array $dates) {
$this->holidays = array_merge($this->holidays, $dates);
return $this;
}
/**
* 添加补班日(周末上班)
*/
public function addWorkday($date) {
$this->workdays[] = $date;
return $this;
}
/**
* 计算工作日
*/
public function calculate($startDate, $endDate) {
$start = new DateTime($startDate);
$end = new DateTime($endDate);
$end->modify('+1 day');
$workingDays = 0;
$period = new DatePeriod($start, new DateInterval('P1D'), $end);
foreach ($period as $date) {
$dateStr = $date->format('Y-m-d');
$dayOfWeek = $date->format('N');
// 检查是否为补班日(周末上班)
if (in_array($dateStr, $this->workdays)) {
$workingDays++;
continue;
}
// 检查是否为节假日
if (in_array($dateStr, $this->holidays)) {
continue;
}
// 普通工作日判断
if ($dayOfWeek < 6) {
$workingDays++;
}
}
return $workingDays;
}
/**
* 获取某日期后的下一个工作日
*/
public function nextWorkingDay($date) {
$current = new DateTime($date);
while (true) {
$current->modify('+1 day');
$dateStr = $current->format('Y-m-d');
$dayOfWeek = $current->format('N');
// 跳过节假日和非周末补班
if (in_array($dateStr, $this->holidays)) {
continue;
}
if (in_array($dateStr, $this->workdays) || $dayOfWeek < 6) {
return $dateStr;
}
}
}
}
// 使用示例
$calculator = new WorkingDaysCalculator();
$calculator->addHolidays([
'2024-01-01', // 元旦
'2024-02-10', '2024-02-11', '2024-02-12', // 春节
'2024-04-04', // 清明节
'2024-05-01', // 劳动节
'2024-06-10', // 端午节
'2024-09-17', // 中秋节
'2024-10-01', // 国庆节
]);
echo $calculator->calculate('2024-01-01', '2024-01-31');
echo $calculator->nextWorkingDay('2024-01-05');
?>
高效数学计算(大数据量)
<?php
/**
* 高效计算工作日(适合大数据量)
*/
function getWorkingDaysFast($startDate, $endDate) {
$start = strtotime($startDate);
$end = strtotime($endDate);
if ($start > $end) {
return 0;
}
// 计算总天数
$totalDays = ceil(($end - $start + 86400) / 86400);
// 计算完整周数
$fullWeeks = floor($totalDays / 7);
$workingDays = $fullWeeks * 5;
// 计算剩余天数
$remainder = $totalDays % 7;
$startDay = date('N', $start);
// 处理剩余天数
for ($i = 0; $i < $remainder; $i++) {
$day = ($startDay + $i - 1) % 7 + 1;
if ($day < 6) {
$workingDays++;
}
}
return $workingDays;
}
// 使用示例
echo getWorkingDaysFast('2024-01-01', '2024-12-31'); // 全年工作日
?>
增加工作日
<?php
/**
* 在指定日期上增加工作日
*/
function addWorkingDays($startDate, $days) {
$date = new DateTime($startDate);
$added = 0;
while ($added < $days) {
$date->modify('+1 day');
if ($date->format('N') < 6) { // 周一至周五
$added++;
}
}
return $date->format('Y-m-d');
}
// 使用示例
echo addWorkingDays('2024-01-01', 10); // 从1月1日起加10个工作日
?>
使用第三方库 Carbon(推荐)
<?php
// 需要先安装 carbon: composer require nesbot/carbon
use Carbon\Carbon;
// 计算工作日
$start = Carbon::parse('2024-01-01');
$end = Carbon::parse('2024-01-31');
$workingDays = 0;
while ($start->lte($end)) {
if ($start->isWeekday()) {
$workingDays++;
}
$start->addDay();
}
echo $workingDays;
// 添加工作日
$date = Carbon::parse('2024-01-01');
$date->addWeekdays(10); // 加10个工作日
echo $date->format('Y-m-d');
?>
实用完整示例
<?php
/**
* 完整的工作日计算类(支持节假日配置)
*/
class WorkdayCalculator {
private $holidays = [];
private $workdays = [];
public function __construct($holidays = [], $workdays = []) {
$this->holidays = $holidays;
$this->workdays = $workdays;
}
public function isWorkday($date) {
$dateStr = is_string($date) ? $date : $date->format('Y-m-d');
$dayOfWeek = date('N', strtotime($dateStr));
// 补班日优先判断
if (in_array($dateStr, $this->workdays)) {
return true;
}
// 节假日判断
if (in_array($dateStr, $this->holidays)) {
return false;
}
// 正常工作日判断
return $dayOfWeek < 6;
}
public function countWorkdays($startDate, $endDate) {
$start = new DateTime($startDate);
$end = new DateTime($endDate);
$end->modify('+1 day');
$count = 0;
$period = new DatePeriod($start, new DateInterval('P1D'), $end);
foreach ($period as $date) {
if ($this->isWorkday($date)) {
$count++;
}
}
return $count;
}
public function getNextWorkday($date, $offset = 1) {
$current = new DateTime($date);
$found = 0;
while ($found < $offset) {
$current->modify('+1 day');
if ($this->isWorkday($current)) {
$found++;
}
}
return $current->format('Y-m-d');
}
public function getPreviousWorkday($date, $offset = 1) {
$current = new DateTime($date);
$found = 0;
while ($found < $offset) {
$current->modify('-1 day');
if ($this->isWorkday($current)) {
$found++;
}
}
return $current->format('Y-m-d');
}
}
// 使用示例
$calculator = new WorkdayCalculator(
// 节假日
['2024-01-01', '2024-02-10', '2024-05-01'],
// 补班日
['2024-02-04']
);
echo "2024年1月工作日:".$calculator->countWorkdays('2024-01-01', '2024-01-31')."\n";
echo "下一个工作日:".$calculator->getNextWorkday('2024-01-05')."\n";
echo "上一个工作日:".$calculator->getPreviousWorkday('2024-01-08')."\n";
?>
注意事项
- 节假日数据:法定节假日每年会变化,建议从配置文件或数据库获取
- 时区设置:确保服务器时区设置正确:
date_default_timezone_set('Asia/Shanghai') - 性能考虑:大数据量计算建议使用数学方法(方法三)
- 边界情况:注意起始日期和结束日期的包含关系
选择哪种方法取决于你的具体需求:
- 简单计算日期差:方法一
- 需要节假日配置:方法二、五
- 大规模计算:方法三
- 常用且完整:方法五(Carbon库)
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播