Reputation: 111
BRIEFING:
I'm trying to calculate the business days between two dates for a custom project management system I'm building. Here's what I made so far as shown below. It seems to be working fine but I'm not sure how accurate it is and whether I should use it or not. Any feedback would be much appreciated!
CODE
<?php
# date variables:
date_default_timezone_set('Asia/Kuwait');
$date['start'] = date('Y-m-d H:i:s');
$date['end'] = '2013-12-01 08:00:00';
$date['off'] = array('Friday','Saturday'); # usual days off in Kuwait)
# calculate the difference:
$date_s = new DateTime($date['start']);
$date_e = new DateTime($date['end']);
$interval = $date_s->diff($date_e);
# obtain relevant values:
$remaining_days = $interval->format('%r%a');
$remaining_weeks = floor($remaining_days/7);
$weekend_days = ($remaining_weeks*count($date['off']));
# additional holidays (just an example):
$extra_holidays_array = array
(
'holiday 1' => '2013-06-24 00:00:00',
'holiday 2' => '2013-06-25 00:00:00',
'holiday 3' => '2013-07-01 00:00:00',
'holiday 4' => '2013-08-24 00:00:00'
);
# check if a real holiday:
$extra_holidays = 0;
foreach( $extra_holidays_array as $check_date )
{
$day_of_holiday = date('l', strtotime($check_date));
if( ! in_array($day_of_holiday,$date['off']) ){ $extra_holidays++; }
}
# total holidays:
$total_holidays = ($weekend_days+$extra_holidays);
# business days:
$business_days_nh = ($remaining_days-$weekend_days); # NO extra holidays
$business_days_wh = ($remaining_days-$weekend_days-$extra_holidays); # WITH extra holidays
?>
<ul>
<li>Current Date: <?php echo $date['start']; ?></li>
<li>Deadline Date: <?php echo $date['end']; ?></li>
</ul>
<ul>
<li>Remaining Days: <?php echo $remaining_days; ?></li>
<li>Remaining Weeks: <?php echo $remaining_weeks; ?></li>
</ul>
<ul>
<li>Usual Holidays: <?php echo $weekend_days; ?></li>
<li>Extra Holidays: <?php echo $extra_holidays; ?></li>
<li>Total Holidays: <?php echo $total_holidays; ?></li>
</ul>
<ul>
<li>Business Days (Before Holidays): <?php echo $business_days_nh; ?></li>
<li>Business Days (After Holidays): <?php echo $business_days_wh; ?></li>
</ul>
Upvotes: 0
Views: 344
Reputation: 9302
I have written a function in a previous project for this exact purpose:
Here is what to use as parameters:
strtotime()
to convert datesImportant Its important to know, timestamps given should be timestamps for the beginning of the day, for example:
To use 1st of January 2013 as a timestamp, use the value of: mktime(0, 0, 0, 1, 1, 2013);
function networkDays($start, $end, array $holidays = array(), $returnAsArray = false)
{
if(!is_int($start)){
trigger_error('Parameter 1 expected to be integer timestamp. ' . ucfirst(gettype($start)) . ' given.', E_USER_WARNING);
return false;
}
if(!is_int($end)){
trigger_error('Parameter 2 expected to be integer timestamp. ' . ucfirst(gettype($start)) . ' given.', E_USER_WARNING);
return false;
}
if(!is_array($holidays)){
$holidays = array();
trigger_error('Parameter 3 expected to be Array. ' . ucfirst(gettype($holidays)) . ' given.', E_USER_NOTICE);
}
if(!is_bool($returnAsArray)){
trigger_error('Parameter 4 expected to be Boolean. ' . ucfirt(gettype($returnAsArray)) . ' given.', E_USER_WARNING);
return false;
}
if($start>=$end){
$nEnd = $start;
$nStart = $end;
$start = $nStart;
$end = $nEnd;
}
foreach($holidays as $key => $holiday)
{
$holidays[$key] = strtotime($holiday);
}
$numberOfDays = ceil(((($end-$start)/60)/60)/24);
$networkDay = 0;
$networkDayArray = array();
for($d = 0; $d < $numberOfDays; $d++)
{
$dayTimestamp = $start+(86400*$d);
if(date('N',$dayTimestamp)<6 && !in_array($dayTimestamp,$holidays))
{
$networkDay += 1;
$networkDayArray[] = $dayTimestamp;
}
}
if($returnAsArray)
{
return $networkDayArray;
} else {
return $networkDay;
}
}
Upvotes: 1