我需要一种在PHP中添加"工作日"的方法.例如,星期五12/5 + 3个工作日= 12月12日星期三.
至少我需要代码来理解周末,但理想情况下它也应该考虑美国联邦假期.我敢肯定,如果有必要,我可以通过蛮力提出解决方案,但我希望那里有更优雅的方法.任何人?
谢谢.
这是PHP手册中date()函数页面上用户注释的函数.这是对评论中早期功能的改进,增加了对闰年的支持.
输入开始日期和结束日期,以及可能介于两者之间的任何假期数组,并以整数形式返回工作日:
The two can be equal in leap years when february has 29 days, the equal sign is added here //In the first case the whole interval is within a week, in the second case the interval falls in two weeks. if ($the_first_day_of_week <= $the_last_day_of_week) { if ($the_first_day_of_week <= 6 && 6 <= $the_last_day_of_week) $no_remaining_days--; if ($the_first_day_of_week <= 7 && 7 <= $the_last_day_of_week) $no_remaining_days--; } else { // (edit by Tokes to fix an edge case where the start day was a Sunday // and the end day was NOT a Saturday) // the day of the week for start is later than the day of the week for end if ($the_first_day_of_week == 7) { // if the start date is a Sunday, then we definitely subtract 1 day $no_remaining_days--; if ($the_last_day_of_week == 6) { // if the end date is a Saturday, then we subtract another day $no_remaining_days--; } } else { // the start date was a Saturday (or earlier), and the end date was (Mon..Fri) // so we skip an entire weekend and subtract 2 days $no_remaining_days -= 2; } } //The no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder //---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it $workingDays = $no_full_weeks * 5; if ($no_remaining_days > 0 ) { $workingDays += $no_remaining_days; } //We subtract the holidays foreach($holidays as $holiday){ $time_stamp=strtotime($holiday); //If the holiday doesn't fall in weekend if ($startDate <= $time_stamp && $time_stamp <= $endDate && date("N",$time_stamp) != 6 && date("N",$time_stamp) != 7) $workingDays--; } return $workingDays; } //Example: $holidays=array("2008-12-25","2008-12-26","2009-01-01"); echo getWorkingDays("2008-12-22","2009-01-02",$holidays) // => will return 7 ?>
获取两个日期之间没有假期的工作日数:
echo number_of_working_days('2013-12-23', '2013-12-29');
3
function number_of_working_days($from, $to) {
$workingDays = [1, 2, 3, 4, 5]; # date format = N (1 = Monday, ...)
$holidayDays = ['*-12-25', '*-01-01', '2013-12-23']; # variable and fixed holidays
$from = new DateTime($from);
$to = new DateTime($to);
$to->modify('+1 day');
$interval = new DateInterval('P1D');
$periods = new DatePeriod($from, $interval, $to);
$days = 0;
foreach ($periods as $period) {
if (!in_array($period->format('N'), $workingDays)) continue;
if (in_array($period->format('Y-m-d'), $holidayDays)) continue;
if (in_array($period->format('*-m-d'), $holidayDays)) continue;
$days++;
}
return $days;
}
date()函数有一些arg 应该有帮助.如果你检查日期("w")它会给你一个星期几的数字,从星期日的0到星期六的6.那么..也许像......
$busDays = 3; $day = date("w"); if( $day > 2 && $day <= 5 ) { /* if between Wed and Fri */ $day += 2; /* add 2 more days for weekend */ } $day += $busDays;
这只是一种可能性的粗略例子.
每个州的假期计算都是非标准的.我正在写一个银行应用程序,我需要一些严格的业务规则,但仍然只能得到一个粗略的标准.
/** * National American Holidays * @param string $year * @return array */ public static function getNationalAmericanHolidays($year) { // January 1 - New Year’s Day (Observed) // Calc Last Monday in May - Memorial Day strtotime("last Monday of May 2011"); // July 4 Independence Day // First monday in september - Labor Day strtotime("first Monday of September 2011") // November 11 - Veterans’ Day (Observed) // Fourth Thursday in November Thanksgiving strtotime("fourth Thursday of November 2011"); // December 25 - Christmas Day $bankHolidays = array( $year . "-01-01" // New Years , "". date("Y-m-d",strtotime("last Monday of May " . $year) ) // Memorial Day , $year . "-07-04" // Independence Day (corrected) , "". date("Y-m-d",strtotime("first Monday of September " . $year) ) // Labor Day , $year . "-11-11" // Veterans Day , "". date("Y-m-d",strtotime("fourth Thursday of November " . $year) ) // Thanksgiving , $year . "-12-25" // XMAS ); return $bankHolidays; }
$startDate = new DateTime( '2013-04-01' ); //intialize start date $endDate = new DateTime( '2013-04-30' ); //initialize end date $holiday = array('2013-04-11','2013-04-25'); //this is assumed list of holiday $interval = new DateInterval('P1D'); // set the interval as 1 day $daterange = new DatePeriod($startDate, $interval ,$endDate); foreach($daterange as $date){ if($date->format("N") <6 AND !in_array($date->format("Y-m-d"),$holiday)) $result[] = $date->format("Y-m-d"); } echo "";print_r($result);
6> Bobbin..:这是一个将商务日添加到日期的功能
function add_business_days($startdate,$buisnessdays,$holidays,$dateformat){ $i=1; $dayx = strtotime($startdate); while($i < $buisnessdays){ $day = date('N',$dayx); $date = date('Y-m-d',$dayx); if($day < 6 && !in_array($date,$holidays))$i++; $dayx = strtotime($date.' +1 day'); } return date($dateformat,$dayx); } //Example date_default_timezone_set('Europe\London'); $startdate = '2012-01-08'; $holidays=array("2012-01-10"); echo 'Start date: '.date('r',strtotime( $startdate)); echo '
'.add_business_days($startdate,7,$holidays,'r');
另一篇文章提到了getWorkingDays(来自php.net评论并包含在这里),但我认为如果你在星期天开始并在一个工作日完成它会中断.
使用以下内容(您需要包含上一篇文章中的getWorkingDays函数)
date_default_timezone_set('Europe\London'); //Example: $holidays = array('2012-01-10'); $startDate = '2012-01-08'; $endDate = '2012-01-13'; echo getWorkingDays( $startDate,$endDate,$holidays);结果为5而不是4
Sun, 08 Jan 2012 00:00:00 +0000 weekend Mon, 09 Jan 2012 00:00:00 +0000 Tue, 10 Jan 2012 00:00:00 +0000 holiday Wed, 11 Jan 2012 00:00:00 +0000 Thu, 12 Jan 2012 00:00:00 +0000 Fri, 13 Jan 2012 00:00:00 +0000以下函数用于生成上述内容.
function get_working_days($startDate,$endDate,$holidays){ $debug = true; $work = 0; $nowork = 0; $dayx = strtotime($startDate); $endx = strtotime($endDate); if($debug){ echo 'get_working_days
'; echo 'startDate: '.date('r',strtotime( $startDate)).'
'; echo 'endDate: '.date('r',strtotime( $endDate)).'
'; var_dump($holidays); echo 'Go to work...'; } while($dayx <= $endx){ $day = date('N',$dayx); $date = date('Y-m-d',$dayx); if($debug)echo '
'.date('r',$dayx).' '; if($day > 5 || in_array($date,$holidays)){ $nowork++; if($debug){ if($day > 5)echo 'weekend'; else echo 'holiday'; } } else $work++; $dayx = strtotime($date.' +1 day'); } if($debug){ echo 'No work: '.$nowork.'
'; echo 'Work: '.$work.'
'; echo 'Work + no work: '.($nowork+$work).'
'; echo 'All seconds / seconds in a day: '.floatval(strtotime($endDate)-strtotime($startDate))/floatval(24*60*60); } return $work; } date_default_timezone_set('Europe\London'); //Example: $holidays=array("2012-01-10"); $startDate = '2012-01-08'; $endDate = '2012-01-13'; //broken echo getWorkingDays( $startDate,$endDate,$holidays); //works echo get_working_days( $startDate,$endDate,$holidays);带上假期......