Calculation of working days

I need a method to add "working days" in PHP. For example, Friday 12/5 + 3 working days = Wednesday 12/10.

At least I need a code to understand the weekend, but ideally it should take into account the US federal holidays. Iโ€™m sure that I will come up with a brute force solution if necessary, but I hope there will be a more elegant approach. Is anyone

Thank.

+98
date php calendar
Dec 03 '08 at 3:07
source share
36 answers
  • one
  • 2

Here's the function from the user comments on the date () function page in the PHP manual. This is an improvement on the earlier feature in the comments, which adds support for leap years.

Enter the start and end dates along with an array of any holidays that may be between them, and returns the working days as an integer:

<?php //The function returns the no. of business days between two dates and it skips the holidays function getWorkingDays($startDate,$endDate,$holidays){ // do strtotime calculations just once $endDate = strtotime($endDate); $startDate = strtotime($startDate); //The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24 //We add one to inlude both dates in the interval. $days = ($endDate - $startDate) / 86400 + 1; $no_full_weeks = floor($days / 7); $no_remaining_days = fmod($days, 7); //It will return 1 if it Monday,.. ,7 for Sunday $the_first_day_of_week = date("N", $startDate); $the_last_day_of_week = date("N", $endDate); //---->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 ?> 
+98
Dec 03 '08 at 3:56
source share

Get the number of non-vacation working days between two dates:

Usage example:

 echo number_of_working_days('2013-12-23', '2013-12-29'); 

Output:

 3 

Functions:

 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('Ym-d'), $holidayDays)) continue; if (in_array($period->format('*-m-d'), $holidayDays)) continue; $days++; } return $days; } 
+81
Oct 07 '13 at 9:38 on
source share

There are several arguments for the date () function, which should help. If you check the date ("w"), he will give you a number for the day of the week, from 0 to Sunday to 6 on Saturday. So .. maybe something like ..

 $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; 

This is just an example of one possibility.

+12
Dec 03 '08 at 3:35
source share

Holiday calculation is non-standard in every state. I am writing a banking application for which I need some tough business rules, but still I can only get an approximate standard.

 /** * 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("Ymd",strtotime("last Monday of May " . $year) ) // Memorial Day , $year . "-07-04" // Independence Day (corrected) , "". date("Ymd",strtotime("first Monday of September " . $year) ) // Labor Day , $year . "-11-11" // Veterans Day , "". date("Ymd",strtotime("fourth Thursday of November " . $year) ) // Thanksgiving , $year . "-12-25" // XMAS ); return $bankHolidays; } 
+11
Nov 29 '12 at 20:01
source share
 $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("Ymd"),$holiday)) $result[] = $date->format("Ymd"); } echo "<pre>";print_r($result); 
+8
Sep 04 '14 at 5:54 on
source share

Here is the function of adding work days to a date

  function add_business_days($startdate,$buisnessdays,$holidays,$dateformat){ $i=1; $dayx = strtotime($startdate); while($i < $buisnessdays){ $day = date('N',$dayx); $date = date('Ym-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 '<p>Start date: '.date('r',strtotime( $startdate)); echo '<p>'.add_business_days($startdate,7,$holidays,'r'); 

Another post mentions getWorkingDays (from php.net's comments and is included here), but I think it breaks if you start on Sunday and end the workday.

Using the following (you need to enable the getWorkingDays function from the previous post)

  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); 

Gives results as 5 not 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 

The following function was used to generate the above function.

  function get_working_days($startDate,$endDate,$holidays){ $debug = true; $work = 0; $nowork = 0; $dayx = strtotime($startDate); $endx = strtotime($endDate); if($debug){ echo '<h1>get_working_days</h1>'; echo 'startDate: '.date('r',strtotime( $startDate)).'<br>'; echo 'endDate: '.date('r',strtotime( $endDate)).'<br>'; var_dump($holidays); echo '<p>Go to work...'; } while($dayx <= $endx){ $day = date('N',$dayx); $date = date('Ym-d',$dayx); if($debug)echo '<br />'.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 '<p>No work: '.$nowork.'<br>'; echo 'Work: '.$work.'<br>'; echo 'Work + no work: '.($nowork+$work).'<br>'; 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); 

Bring the holidays ...

+6
Dec 02 '09 at 1:59
source share

You can try this feature, which is simpler.

 function getWorkingDays($startDate, $endDate) { $begin = strtotime($startDate); $end = strtotime($endDate); if ($begin > $end) { return 0; } else { $no_days = 0; while ($begin <= $end) { $what_day = date("N", $begin); if (!in_array($what_day, [6,7]) ) // 6 and 7 are weekend $no_days++; $begin += 86400; // +1 day }; return $no_days; } } 
+3
Sep 08 '15 at 13:53 on
source share

The function of adding or subtracting business days from a certain date, this does not take into account holidays.

 function dateFromBusinessDays($days, $dateTime=null) { $dateTime = is_null($dateTime) ? time() : $dateTime; $_day = 0; $_direction = $days == 0 ? 0 : intval($days/abs($days)); $_day_value = (60 * 60 * 24); while($_day !== $days) { $dateTime += $_direction * $_day_value; $_day_w = date("w", $dateTime); if ($_day_w > 0 && $_day_w < 6) { $_day += $_direction * 1; } } return $dateTime; } 

use so ...

 echo date("m/d/Y", dateFromBusinessDays(-7)); echo date("m/d/Y", dateFromBusinessDays(3, time() + 3*60*60*24)); 
+2
Jun 19 '10 at 16:23
source share

My version based on the work of @mcgrailm ... has changed because the report had to be reviewed within 3 business days, and if it was sent over the weekend, the counting will start next Monday:

 function business_days_add($start_date, $business_days, $holidays = array()) { $current_date = strtotime($start_date); $business_days = intval($business_days); // Decrement does not work on strings while ($business_days > 0) { if (date('N', $current_date) < 6 && !in_array(date('Ym-d', $current_date), $holidays)) { $business_days--; } if ($business_days > 0) { $current_date = strtotime('+1 day', $current_date); } } return $current_date; } 

And having developed the difference of two dates on business days:

 function business_days_diff($start_date, $end_date, $holidays = array()) { $business_days = 0; $current_date = strtotime($start_date); $end_date = strtotime($end_date); while ($current_date <= $end_date) { if (date('N', $current_date) < 6 && !in_array(date('Ym-d', $current_date), $holidays)) { $business_days++; } if ($current_date <= $end_date) { $current_date = strtotime('+1 day', $current_date); } } return $business_days; } 

As a note, everyone who uses 86400, or 24 * 60 * 60, please donโ€™t ... your forgetting time changes from winter / summer time, where it is not exactly 24 hours a day. Although it is a bit slower than strtotime ('+ 1 day', $ timestamp), it is much more reliable.

+2
Oct 14 2018-11-11T00:
source share

A rough attempt to determine working hours - from Monday to Friday from 8:00 to 16:00:

 if (date('N')<6 && date('G')>8 && date('G')<16) { // we have a working time (or check for holidays) } 
+2
Dec 07 '11 at 23:37
source share

I created a decent library for this.

https://github.com/andrejsstepanovs/business-days-calculator

It is stable and ready for production.

+2
Jan 06 '15 at 10:59
source share

Below is the work code for calculating work days from a specific date.

 <?php $holiday_date_array = array("2016-01-26", "2016-03-07", "2016-03-24", "2016-03-25", "2016-04-15", "2016-08-15", "2016-09-12", "2016-10-11", "2016-10-31"); $date_required = "2016-03-01"; function increase_date($date_required, $holiday_date_array=array(), $days = 15){ if(!empty($date_required)){ $counter_1=0; $incremented_date = ''; for($i=1; $i <= $days; $i++){ $date = strtotime("+$i day", strtotime($date_required)); $day_name = date("D", $date); $incremented_date = date("Ymd", $date); if($day_name=='Sat'||$day_name=='Sun'|| in_array($incremented_date ,$holiday_date_array)==true){ $counter_1+=1; } } if($counter_1 > 0){ return increase_date($incremented_date, $holiday_date_array, $counter_1); }else{ return $incremented_date; } }else{ return 'invalid'; } } echo increase_date($date_required, $holiday_date_array, 15); ?> //output after adding 15 business working days in 2016-03-01 will be "2016-03-23" 
+2
Mar 17 '16 at 6:06
source share

Here is another solution without a cycle for every day.

 $from = new DateTime($first_date); $to = new DateTime($second_date); $to->modify('+1 day'); $interval = $from->diff($to); $days = $interval->format('%a'); $extra_days = fmod($days, 7); $workdays = ( ( $days - $extra_days ) / 7 ) * 5; $first_day = date('N', strtotime($first_date)); $last_day = date('N', strtotime("1 day", strtotime($second_date))); $extra = 0; if($first_day > $last_day) { if($first_day == 7) { $first_day = 6; } $extra = (6 - $first_day) + ($last_day - 1); if($extra < 0) { $extra = $extra * -1; } } if($last_day > $first_day) { $extra = $last_day - $first_day; } $days = $workdays + $extra 
+2
Dec 05 '17 at 11:21 on
source share

On holidays, create an array of days in some format that date () can give. Example:

 // I know, these aren't holidays $holidays = array( 'Jan 2', 'Feb 3', 'Mar 5', 'Apr 7', // ... ); 

Then use in_array () and date () to check if the timestamp is a holiday:

 $day_of_year = date('M j', $timestamp); $is_holiday = in_array($day_of_year, $holidays); 
+1
Dec 03 2018-08-12T00:
source share

I had the same need, I started with the first example of a bobbin and ended with this

  function add_business_days($startdate,$buisnessdays,$holidays=array(),$dateformat){ $enddate = strtotime($startdate); $day = date('N',$enddate); while($buisnessdays > 1){ $enddate = strtotime(date('Ym-d',$enddate).' +1 day'); $day = date('N',$enddate); if($day < 6 && !in_array($enddate,$holidays))$buisnessdays--; } return date($dateformat,$enddate); } 

hth someone

+1
Jun 29 '10 at 15:36
source share
 <?php // $today is the UNIX timestamp for today date $today = time(); echo "<strong>Today is (ORDER DATE): " . '<font color="red">' . date('l, F j, Y', $today) . "</font></strong><br/><br/>"; //The numerical representation for day of week (Ex. 01 for Monday .... 07 for Sunday $today_numerical = date("N",$today); //leadtime_days holds the numeric value for the number of business days $leadtime_days = $_POST["leadtime"]; //leadtime is the adjusted date for shipdate $shipdate = time(); while ($leadtime_days > 0) { if ($today_numerical != 5 && $today_numerical != 6) { $shipdate = $shipdate + (60*60*24); $today_numerical = date("N",$shipdate); $leadtime_days --; } else $shipdate = $shipdate + (60*60*24); $today_numerical = date("N",$shipdate); } echo '<strong>Estimated Ship date: ' . '<font color="green">' . date('l, F j, Y', $shipdate) . "</font></strong>"; ?> 
+1
Oct 07 '10 at 17:20
source share

Option 1:

 <?php /* * Does not count current day, the date returned is the last business day * Requires PHP 5.1 (Using ISO-8601 week) */ function businessDays($timestamp = false, $bDays = 2) { if($timestamp === false) $timestamp = time(); while ($bDays>0) { $timestamp += 86400; if (date('N', $timestamp)<6) $bDays--; } return $timestamp; } 

Option 2:

 <?php /* * Does not count current day, the date returned is a business day * following the last business day * Requires PHP 5.1 (Using ISO-8601 week) */ function businessDays($timestamp = false, $bDays = 2) { if($timestamp === false) $timestamp = time(); while ($bDays+1>0) { $timestamp += 86400; if (date('N', $timestamp)<6) $bDays--; } return $timestamp; } 

Option 3:

 <?php /* * Does not count current day, the date returned is * a date following the last business day (can be weekend or not. * See above for alternatives) * Requires PHP 5.1 (Using ISO-8601 week) */ function businessDays($timestamp = false, $bDays = 2) { if($timestamp === false) $timestamp = time(); while ($bDays>0) { $timestamp += 86400; if (date('N', $timestamp)<6) $bDays--; } return $timestamp += 86400; } 

Additional leisure options can be made using the options of the above by doing the following. The note! make sure that all timestamps are the same time of the day (i.e. midnight).

Make an array of holiday dates (like unixtimestamps), i.e.:

 $holidays = array_flip(strtotime('2011-01-01'),strtotime('2011-12-25')); 

Change line:

 if (date('N', $timestamp)<6) $bDays--; 

:

 if (date('N', $timestamp)<6 && !isset($holidays[$timestamp])) $bDays--; 

Done!

 <?php /* * Does not count current day, the date returned is the last business day * Requires PHP 5.1 (Using ISO-8601 week) */ function businessDays($timestamp = false, $bDays = 2) { if($timestamp === false) $timestamp = strtotime(date('Ym-d',time())); $holidays = array_flip(strtotime('2011-01-01'),strtotime('2011-12-25')); while ($bDays>0) { $timestamp += 86400; if (date('N', $timestamp)<6 && !isset($holidays[$timestamp])) $bDays--; } return $timestamp; } 
+1
Mar 02 2018-11-11T00:
source share
 <?php function AddWorkDays(){ $i = 0; $d = 5; // Number of days to add while($i <= $d) { $i++; if(date('N', mktime(0, 0, 0, date(m), date(d)+$i, date(Y))) < 5) { $d++; } } return date(Y).','.date(m).','.(date(d)+$d); } ?> 
+1
Apr 7 2018-11-11T00:
source share

Here is a recursive solution. It can be easily changed to track and return the latest date.

 // Returns a $numBusDays-sized array of all business dates, // starting from and including $currentDate. // Any date in $holidays will be skipped over. function getWorkingDays($currentDate, $numBusDays, $holidays = array(), $resultDates = array()) { // exit when we have collected the required number of business days if ($numBusDays === 0) { return $resultDates; } // add current date to return array, if not a weekend or holiday $date = date("w", strtotime($currentDate)); if ( $date != 0 && $date != 6 && !in_array($currentDate, $holidays) ) { $resultDates[] = $currentDate; $numBusDays -= 1; } // set up the next date to test $currentDate = new DateTime("$currentDate + 1 day"); $currentDate = $currentDate->format('Ym-d'); return getWorkingDays($currentDate, $numBusDays, $holidays, $resultDates); } // test $days = getWorkingDays('2008-12-05', 4); print_r($days); 
+1
Mar 21 '12 at 21:50
source share
 date_default_timezone_set('America/New_York'); /** Given a number days out, what day is that when counting by 'business' days * get the next business day. by default it looks for next business day * ie calling $date = get_next_busines_day(); on monday will return tuesday * $date = get_next_busines_day(2); on monday will return wednesday * $date = get_next_busines_day(2); on friday will return tuesday * * @param $number_of_business_days (integer) how many business days out do you want * @param $start_date (string) strtotime parseable time value * @param $ignore_holidays (boolean) true/false to ignore holidays * @param $return_format (string) as specified in php.net/date */ function get_next_business_day($number_of_business_days=1,$start_date='today',$ignore_holidays=false,$return_format='m/d/y') { // get the start date as a string to time $result = strtotime($start_date); // now keep adding to today date until number of business days is 0 and we land on a business day while ($number_of_business_days > 0) { // add one day to the start date $result = strtotime(date('Ym-d',$result) . " + 1 day"); // this day counts if it a weekend and not a holiday, or if we choose to ignore holidays if (is_weekday(date('Ym-d',$result)) && (!(is_holiday(date('Ym-d',$result))) || $ignore_holidays) ) $number_of_business_days--; } // when my $number of business days is exausted I have my final date return(date($return_format,$result)); } function is_weekend($date) { // return if this is a weekend date or not. return (date('N', strtotime($date)) >= 6); } function is_weekday($date) { // return if this is a weekend date or not. return (date('N', strtotime($date)) < 6); } function is_holiday($date) { // return if this is a holiday or not. // what are my holidays for this year $holidays = array("New Year Day 2011" => "12/31/10", "Good Friday" => "04/06/12", "Memorial Day" => "05/28/12", "Independence Day" => "07/04/12", "Floating Holiday" => "12/31/12", "Labor Day" => "09/03/12", "Thanksgiving Day" => "11/22/12", "Day After Thanksgiving Day" => "11/23/12", "Christmas Eve" => "12/24/12", "Christmas Day" => "12/25/12", "New Year Day 2012" => "01/02/12", "New Year Day 2013" => "01/01/13" ); return(in_array(date('m/d/y', strtotime($date)),$holidays)); } print get_next_business_day(1) . "\n"; 
+1
May 31 '12 at 16:17
source share

Calculate workdays between two dates, including holidays and custom workweek

The answer is not so trivial, so my suggestion would be to use a class in which you can configure more than relying on a simplified function (or assuming a fixed locale and culture). To receive a date after a certain number of working days, you:

Functional approach

 /** * @param days, int * @param $format, string: dateformat (if format defined OTHERWISE int: timestamp) * @param start, int: timestamp (mktime) default: time() //now * @param $wk, bit[]: flags for each workday (0=SUN, 6=SAT) 1=workday, 0=day off * @param $holiday, string[]: list of dates, YYYY-MM-DD, MM-DD */ function working_days($days, $format='', $start=null, $week=[0,1,1,1,1,1,0], $holiday=[]) { if(is_null($start)) $start = time(); if($days <= 0) return $start; if(count($week) != 7) trigger_error('workweek must contain bit-flags for 7 days'); if(array_sum($week) == 0) trigger_error('workweek must contain at least one workday'); $wd = date('w', $start);//0=sun, 6=sat $time = $start; while($days) { if( $week[$wd] && !in_array(date('Ym-d', $time), $holiday) && !in_array(date('m-d', $time), $holiday) ) --$days; //decrement on workdays $wd = date('w', $time += 86400); //add one day in seconds } $time -= 86400;//include today return $format ? date($format, $time): $time; } //simple usage $ten_days = working_days(10, 'DF d Y'); echo '<br>ten workingdays (MON-FRI) disregarding holidays: ',$ten_days; //work on saturdays and add new years day as holiday $ten_days = working_days(10, 'DF d Y', null, [0,1,1,1,1,1,1], ['01-01']); echo '<br>ten workingdays (MON-SAT) disregarding holidays: ',$ten_days; 
+1
May 20 '15 at 9:47
source share

This is another solution, it is almost 25% faster than checking holidays with in_array:

 /** * Function to calculate the working days between two days, considering holidays. * @param string $startDate -- Start date of the range (included), formatted as Ymd. * @param string $endDate -- End date of the range (included), formatted as Ymd. * @param array(string) $holidayDates -- OPTIONAL. Array of holidays dates, formatted as Ymd. (eg array("2016-08-15", "2016-12-25")) * @return int -- Number of working days. */ function getWorkingDays($startDate, $endDate, $holidayDates=array()){ $dateRange = new DatePeriod(new DateTime($startDate), new DateInterval('P1D'), (new DateTime($endDate))->modify("+1day")); foreach ($dateRange as $dr) { if($dr->format("N")<6){$workingDays[]=$dr->format("Ymd");} } return count(array_diff($workingDays, $holidayDates)); } 
+1
Nov 18 '16 at 10:33
source share

I know I'm late for the party, but I use this old set of Marcos Montes functions to define weekends and workdays. He took the time to add an algorithm from 1876 for Easter, and he added all the major American holidays. It can be easily updated for other countries.

 //Usage $days = 30; $next_working_date = nextWorkingDay($days, $somedate); //add date function function DateAdd($interval, $number, $date) { $date_time_array = getdate($date); //die(print_r($date_time_array)); $hours = $date_time_array["hours"]; $minutes = $date_time_array["minutes"]; $seconds = $date_time_array["seconds"]; $month = $date_time_array["mon"]; $day = $date_time_array["mday"]; $year = $date_time_array["year"]; switch ($interval) { case "yyyy": $year+=$number; break; case "q": $year+=($number*3); break; case "m": $month+=$number; break; case "y": case "d": case "w": $day+=$number; break; case "ww": $day+=($number*7); break; case "h": $hours+=$number; break; case "n": $minutes+=$number; break; case "s": $seconds+=$number; break; } // echo "day:" . $day; $timestamp= mktime($hours,$minutes,$seconds,$month,$day,$year); return $timestamp; } // the following function get_holiday() is based on the work done by // Marcos J. Montes function get_holiday($year, $month, $day_of_week, $week="") { if ( (($week != "") && (($week > 5) || ($week < 1))) || ($day_of_week > 6) || ($day_of_week < 0) ) { // $day_of_week must be between 0 and 6 (Sun=0, ... Sat=6); $week must be between 1 and 5 return FALSE; } else { if (!$week || ($week == "")) { $lastday = date("t", mktime(0,0,0,$month,1,$year)); $temp = (date("w",mktime(0,0,0,$month,$lastday,$year)) - $day_of_week) % 7; } else { $temp = ($day_of_week - date("w",mktime(0,0,0,$month,1,$year))) % 7; } if ($temp < 0) { $temp += 7; } if (!$week || ($week == "")) { $day = $lastday - $temp; } else { $day = (7 * $week) - 6 + $temp; } //echo $year.", ".$month.", ".$day . "<br><br>"; return format_date($year, $month, $day); } } function observed_day($year, $month, $day) { // sat -> fri & sun -> mon, any exceptions? // // should check $lastday for bumping forward and $firstday for bumping back, // although New Year & Easter look to be the only holidays that potentially // move to a different month, and both are accounted for. $dow = date("w", mktime(0, 0, 0, $month, $day, $year)); if ($dow == 0) { $dow = $day + 1; } elseif ($dow == 6) { if (($month == 1) && ($day == 1)) { // New Year on a Saturday $year--; $month = 12; $dow = 31; } else { $dow = $day - 1; } } else { $dow = $day; } return format_date($year, $month, $dow); } function calculate_easter($y) { // In the text below, 'intval($var1/$var2)' represents an integer division neglecting // the remainder, while % is division keeping only the remainder. So 30/7=4, and 30%7=2 // // This algorithm is from Practical Astronomy With Your Calculator, 2nd Edition by Peter // Duffett-Smith. It was originally from Butcher Ecclesiastical Calendar, published in // 1876. This algorithm has also been published in the 1922 book General Astronomy by // Spencer Jones; in The Journal of the British Astronomical Association (Vol.88, page // 91, December 1977); and in Astronomical Algorithms (1991) by Jean Meeus. $a = $y%19; $b = intval($y/100); $c = $y%100; $d = intval($b/4); $e = $b%4; $f = intval(($b+8)/25); $g = intval(($b-$f+1)/3); $h = (19*$a+$b-$d-$g+15)%30; $i = intval($c/4); $k = $c%4; $l = (32+2*$e+2*$i-$h-$k)%7; $m = intval(($a+11*$h+22*$l)/451); $p = ($h+$l-7*$m+114)%31; $EasterMonth = intval(($h+$l-7*$m+114)/31); // [3 = March, 4 = April] $EasterDay = $p+1; // (day in Easter Month) return format_date($y, $EasterMonth, $EasterDay); } function nextWorkingDay($number_days, $start_date = "") { $day_counter = 0; $intCounter = 0; if ($start_date=="") { $today = mktime(0, 0, 0, date("m") , date("d"), date("Y")); } else { $start_time = strtotime($start_date); $today = mktime(0, 0, 0, date("m", $start_time) , date("d", $start_time), date("Y", $start_time)); } while($day_counter < $number_days) { $working_time = DateAdd("d", 1, $today); $working_date = date("Ymd", $working_date); if (!isWeekend($working_date) && !confirm_holiday(date("Ymd", strtotime($working_date))) ) { $day_counter++; } $intCounter++; $today = $working_time; if ($intCounter > 1000) { //just in case out of control? break; } } return $working_date; } function isWeekend($check_date) { return (date("N", strtotime($check_date)) > 5); } function confirm_holiday($somedate="") { if ($somedate=="") { $somedate = date("Ymd"); } $year = date("Y", strtotime($somedate)); $blnHoliday = false; //newyears if ($somedate == observed_day($year, 1, 1)) { $blnHoliday = true; } if ($somedate == format_date($year, 1, 1)) { $blnHoliday = true; } if ($somedate == format_date($year, 12, 31)) { $blnHoliday = true; } //Martin Luther King if ($somedate == get_holiday($year, 1, 1, 3)) { $blnHoliday = true; } //President's if ($somedate == get_holiday($year, 2, 1, 3)) { $blnHoliday = true; } //easter if ($somedate == calculate_easter($year)) { $blnHoliday = true; } //Memorial if ($somedate == get_holiday($year, 5, 1)) { $blnHoliday = true; } //july4 if ($somedate == observed_day($year, 7, 4)) { $blnHoliday = true; } //labor if ($somedate == get_holiday($year, 9, 1, 1)) { $blnHoliday = true; } //columbus if ($somedate == get_holiday($year, 10, 1, 2)) { $blnHoliday = true; } //thanks if ($somedate == get_holiday($year, 11, 4, 4)) { $blnHoliday = true; } //xmas if ($somedate == format_date($year, 12, 24)) { $blnHoliday = true; } if ($somedate == format_date($year, 12, 25)) { $blnHoliday = true; } return $blnHoliday; } 
+1
Jan 19 '17 at 19:16
source share

This piece of code is very easy to calculate the working day without the end of the week and holidays:

 function getWorkingDays($startDate,$endDate,$offdays,$holidays){ $endDate = strtotime($endDate); $startDate = strtotime($startDate); $days = ($endDate - $startDate) / 86400 + 1; $counter=0; for ($i = 1; $i <= $days; $i++) { $the_first_day_of_week = date("N", $startDate); $startDate+=86400; if (!in_array($the_first_day_of_week, $offdays) && !in_array(date("Ym- d",$startDate), $holidays)) { $counter++; } } return $counter; } //example to use $holidays=array("2017-07-03","2017-07-20"); $offdays=array(5,6);//weekend days Monday=1 .... Sunday=7 echo getWorkingDays("2017-01-01","2017-12-31",$offdays,$holidays) 
+1
Aug 01 '17 at 7:34 on
source share

function get_business_days_forward_from_date ($ num_days, $ start_date = '', $ rtn_fmt = 'Ym-d') {

 // $start_date will default to today if ($start_date=='') { $start_date = date("Ymd"); } $business_day_ct = 0; $max_days = 10000 + $num_days; // to avoid any possibility of an infinite loop // define holidays, this currently only goes to 2012 because, well, you know... ;-) // if the world is still here after that, you can find more at // http://www.opm.gov/Operating_Status_Schedules/fedhol/2013.asp // always add holidays in order, because the iteration will stop when the holiday is > date being tested $fed_holidays=array( "2010-01-01", "2010-01-18", "2010-02-15", "2010-05-31", "2010-07-05", "2010-09-06", "2010-10-11", "2010-11-11", "2010-11-25", "2010-12-24", "2010-12-31", "2011-01-17", "2011-02-21", "2011-05-30", "2011-07-04", "2011-09-05", "2011-10-10", "2011-11-11", "2011-11-24", "2011-12-26", "2012-01-02", "2012-01-16", "2012-02-20", "2012-05-28", "2012-07-04", "2012-09-03", "2012-10-08", "2012-11-12", "2012-11-22", "2012-12-25", ); $curr_date_ymd = date('Ym-d', strtotime($start_date)); for ($x=1;$x<$max_days;$x++) { if (intval($num_days)==intval($business_day_ct)) { return(date($rtn_fmt, strtotime($curr_date_ymd))); } // date found - return // get next day to check $curr_date_ymd = date('Ym-d', (strtotime($start_date)+($x * 86400))); // add 1 day to the current date $is_business_day = 1; // check if this is a weekend 1 (for Monday) through 7 (for Sunday) if ( intval(date("N",strtotime($curr_date_ymd))) > 5) { $is_business_day = 0; } //check for holiday foreach($fed_holidays as $holiday) { if (strtotime($holiday)==strtotime($curr_date_ymd)) // holiday found { $is_business_day = 0; break 1; } if (strtotime($holiday)>strtotime($curr_date_ymd)) { break 1; } // past date, stop searching (always add holidays in order) } $business_day_ct = $business_day_ct + $is_business_day; // increment if this is a business day } // if we get here, you are hosed return ("ERROR"); 

}

0
02 . '10 15:36
source share

, Bobbin mcgrailm, , .

 function add_business_days($startdate,$buisnessdays,$holidays,$dateformat){ $enddate = strtotime($startdate); $day = date('N',$enddate); while($buisnessdays > 0){ // compatible with 1 businessday if I'll need it $enddate = strtotime(date('Ym-d',$enddate).' +1 day'); $day = date('N',$enddate); if($day < 6 && !in_array(date('Ym-d',$enddate),$holidays))$buisnessdays--; } return date($dateformat,$enddate); } // as a parameter in in_array function we should use endate formated to // compare correctly with the holidays array. 
0
25 . '11 3:17
source share

add_business_days . , .

= = 1 Holidays array = .

.

 function add_business_days($startdate, $buisnessdays, $holidays = array(), $dateformat = 'Ym-d'){ $i= 1; $dayx= strtotime($startdate); $buisnessdays= ceil($buisnessdays); while($i < $buisnessdays) { $day= date('N',$dayx); $date= date('Ym-d',$dayx); if($day < 6 && !in_array($date,$holidays)) $i++; $dayx= strtotime($date.' +1 day'); } ## If the calculated day falls on a weekend or is a holiday, then add days to the next business day $day= date('N',$dayx); $date= date('Ym-d',$dayx); while($day >= 6 || in_array($date,$holidays)) { $dayx= strtotime($date.' +1 day'); $day= date('N',$dayx); $date= date('Ym-d',$dayx); } return date($dateformat, $dayx);} 
0
04 . '11 8:20
source share

, , 4 ( 4 !), ...

/**
*
* @param string $year
* @return array
* /
public static function getNationalAmericanHolidays ($ year) {

 // January 1 - New Year Day (Observed) // Third Monday in January - Birthday of Martin Luther King, Jr. // Third Monday in February - Washington's Birthday / President Day // Last Monday in May - Memorial Day // July 4 - Independence Day // First Monday in September - Labor Day // Second Monday in October - Columbus Day // November 11 - Veterans' Day (Observed) // Fourth Thursday in November Thanksgiving Day // December 25 - Christmas Day $bankHolidays = array( ['New Years Day'] => $year . "-01-01", ['Martin Luther King Jr Birthday'] => "". date("Ymd",strtotime("third Monday of January " . $year) ), ['Washingtons Birthday'] => "". date("Ymd",strtotime("third Monday of February " . $year) ), ['Memorial Day'] => "". date("Ymd",strtotime("last Monday of May " . $year) ), ['Independance Day'] => $year . "-07-04", ['Labor Day'] => "". date("Ymd",strtotime("first Monday of September " . $year) ), ['Columbus Day'] => "". date("Ymd",strtotime("second Monday of October " . $year) ), ['Veterans Day'] => $year . "-11-11", ['Thanksgiving Day'] => "". date("Ymd",strtotime("fourth Thursday of November " . $year) ), ['Christmas Day'] => $year . "-12-25" ); return $bankHolidays; 

}

0
Jan 14 '13 13:08
source share

API, ( :-); , - .

~ Nate

PHP

0
09 . '13 3:17
source share

Bobbin, mcgrailm, Tony, James Pasta , . , , , . , / . . , .

 <?php function count_business_days($date, $days, $holidays) { $date = strtotime($date); for ($i = 1; $i <= intval($days); $i++) { //Loops each day count //First, find the next available weekday because this might be a weekend/holiday while (date('N', $date) >= 6 || in_array(date('Ym-d', $date), $holidays)){ $date = strtotime(date('Ym-d',$date).' +1 day'); } //Now that we know we have a business day, add 1 day to it $date = strtotime(date('Ym-d',$date).' +1 day'); //If this day that was previously added falls on a weekend/holiday, then find the next business day while (date('N', $date) >= 6 || in_array(date('Ym-d', $date), $holidays)){ $date = strtotime(date('Ym-d',$date).' +1 day'); } } return date('Ym-d', $date); } //Also add in the code from Tony and James Pasta to handle holidays... function getNationalAmericanHolidays($year) { $bankHolidays = array( 'New Years Day' => $year . "-01-01", 'Martin Luther King Jr Birthday' => "". date("Ymd",strtotime("third Monday of January " . $year) ), 'Washingtons Birthday' => "". date("Ymd",strtotime("third Monday of February " . $year) ), 'Memorial Day' => "". date("Ymd",strtotime("last Monday of May " . $year) ), 'Independance Day' => $year . "-07-04", 'Labor Day' => "". date("Ymd",strtotime("first Monday of September " . $year) ), 'Columbus Day' => "". date("Ymd",strtotime("second Monday of October " . $year) ), 'Veterans Day' => $year . "-11-11", 'Thanksgiving Day' => "". date("Ymd",strtotime("fourth Thursday of November " . $year) ), 'Christmas Day' => $year . "-12-25" ); return $bankHolidays; } //Now to call it... since we're working with business days, we should //also be working with business hours so check if it after 5 PM //and go to the next day if necessary. //Go to next day if after 5 pm (5 pm = 17) if (date(G) >= 17) { $start_date = date("Ymd", strtotime("+ 1 day")); //Tomorrow } else { $start_date = date("Ymd"); //Today } //Get the holidays for the current year and also for the next year $this_year = getNationalAmericanHolidays(date('Y')); $next_year = getNationalAmericanHolidays(date('Y', strtotime("+12 months"))); $holidays = array_merge($this_year, $next_year); //The number of days to count $days_count = 10; echo count_business_days($start_date, $days_count, $holidays); ?> 
0
09 . '13 22:50
source share
  • one
  • 2



All Articles