Calculating Business Days in PHP
Posted on
For one of my client’s projects, The Superdups Self-Service Quoter, I had to write an algorithm to estimate due date of each order based on a selected turn around time in business days. This would probably be a simply task in Ruby on Rails, but unfortunately, that wasn’t an option.
The Code
class DateHelper {
// Holidays must be in order
var $holidays = array("2010-07-04", "2010-09-06", "2010-09-23", "2010-10-11", "2010-11-01", "2010-11-11", "2010-11-25", "2010-12-25");
const oneday = 86400; // 86400 seconds = 1 Day
const weekend = 172800; // 172800 seconds = 2 Days
function addBusinessDays($start_date, $business_days) {
// If $start_date is on the weekend, start on following Monday
if (date('N', $start_date) == 6) { // If start date is on Saturday
$new_start_date = $start_date + self::weekend;
} elseif (date('N', $start_date) == 7) { // If start date is on Sunday
$new_start_date = $start_date + self::oneday;
} else {
$new_start_date = $start_date;
}
// Add business days to the start date
$due_date = $new_start_date + $business_days * self::oneday;
// For every 5 business days, add 2 more for the weekend
$due_date += floor($business_days / 5) * self::weekend;
// If remainder of business days causes due date to land on or after the weekend
if (($business_days % 5) + date('N', $new_start_date) >= 6) {
$due_date += self::weekend; // Add 2 days to compensate for the weekend
}
foreach($this->holidays as $holiday){
$time_stamp = strtotime($holiday);
// If the holiday falls between the start date and end date
// and is on a weekday
// Or if $new_start_date is on a holiday
if (($start_date <= $time_stamp && $time_stamp <= $due_date && date("N", $time_stamp) < 6) || date("Y-m-d", $new_start_date) == $holiday) {
$due_date += self::oneday;
if (date('N', $due_date) >= 6) {
// If due date on Saturday or Sunday
$due_date += self::weekend;
}
}
}
return $due_date;
}
}
Usage
addBusinessDays ( int $start_date , int $business_days )
$date = new DateHelper;
$start = time();
echo date("l, M d, Y", $start);
echo "\n+ 0 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 0));
echo "\n+ 1 Day = " . date("l, M d, Y", $date->addBusinessDays($start, 1));
echo "\n+ 2 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 2));
echo "\n+ 3 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 3));
echo "\n+ 4 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 4));
echo "\n+ 5 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 5));
echo "\n+ 6 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 6));
echo "\n+ 7 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 7));
echo "\n+ 8 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 8));
echo "\n+ 9 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 9));
echo "\n+ 10 Days = " . date("l, M d, Y", $date->addBusinessDays($start, 10));
Result
Friday, Jun 04, 2010 + 0 Days = Friday, Jun 04, 2010 + 1 Day = Monday, Jun 07, 2010 + 2 Days = Tuesday, Jun 08, 2010 + 3 Days = Wednesday, Jun 09, 2010 + 4 Days = Thursday, Jun 10, 2010 + 5 Days = Friday, Jun 11, 2010 + 6 Days = Monday, Jun 14, 2010 + 7 Days = Tuesday, Jun 15, 2010 + 8 Days = Wednesday, Jun 16, 2010 + 9 Days = Thursday, Jun 17, 2010 + 10 Days = Friday, Jun 18, 2010Usage Notes
- Method requires a Unix timestamp for
$start_date - Method will return a Unix timestamp
- Entering a zero for
$business_dayswill return the closest business day (the current day if it is a business day, or the next business day if it isn’t) - This script assumes business days to be Monday - Friday, minus holidays.
- Don’t forget to set
$holidaysto any non-weekend, non-business days. Weekend holidays will be ignored. The script may come up with the wrong result if the holidays are out of order - Requires PHP 5.1.0+ (for the “N” in
date("N", $time_stamp))